factory

package
v4.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 10, 2023 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrFactoryTypeAlreadyExists is returned when a creator function is registered for a type that already exists.
	ErrFactoryTypeAlreadyExists = errors.New("a creator function for the type already exists")
	// ErrFactoryTypeDoesNotExist is returned when a new object is requrested for an unregistered type.
	ErrFactoryTypeDoesNotExist = errors.New("factory type not found")
	// ErrNilConfig is returned when a nil config is passed to a factory.
	ErrNilConfig = errors.New("factory config is nil")
	// ErrMissingDependency is returned when a creator function fails to find a required dependency.
	ErrMissingDependency = errors.New("creator function did not receive required dependency")
	// ErrInvalidDependency is returned when a creator function finds an invalid dependency (e.g. wrong type, not
	// initialized, etc.).
	ErrInvalidDependency = errors.New("creator function received invalid dependency")
)

Functions

func CallFactories

func CallFactories(factoryCalls Calls) error

CallFactories receives a slice of Call and calls the Factory.New method of each Factory. If a factory return an error, the function returns the error immediately.

func ErrorWithContext

func ErrorWithContext(err error) error

ErrorWithContext wraps an error with information about the function that generated the error.

func SetValue

func SetValue(out interface{}, value interface{}) error

SetValue sets the `out` parameter to the specified value. It should be called by factory creation functions to set `out`'s output value. `out` must be a pointer to a value able to contain the expected type.

func SetValueAndValidate

func SetValueAndValidate(out interface{}, value interface{}) error

SetValueAndValidate sets the `out` parameter to the specified value. The `out` value is validated if it implements validate.Validator.

Types

type Call

type Call struct {
	Factory      Factory
	Config       *Config
	Dependencies Dependencies
	Out          interface{}
}

Call contains a Factory and all parameters required to call Factory.New. It is used together with CallFactories to get the result of calling multiple factories in a single call.

type Calls

type Calls []Call

Calls is a slice of Call.

type Config

type Config struct {
	// Type returns the object type to create using a factory.
	Type string `yaml:"type"`
	// Config contains configuration data required by the factory to create the request object.
	// Note that the factory creating the object has no way to know about the implementation details of the object
	// being created. As such, the NewFunc creating the object will need to marshal the data contained in the config.
	Config ConfigValues `yaml:"config"`
}

Config is a factory configuration. It is passed to a factory to request a component type and provide it with configuration information.

type ConfigValues

type ConfigValues map[string]interface{}

ConfigValues contains configuration values for a Config.

type Dependencies

type Dependencies map[string]interface{}

Dependencies is a container for a set of dependencies. A dependency is an object or value that is not initialized by the factory and cannot be obtained from the config. It is recommended that a received Dependencies object is marshalled onto a concrete struct before being used. Read the ToStruct documentation for an in-depth explanation.

func NewDependencies

func NewDependencies() Dependencies

NewDependencies returns a new Dependencies object.

func (Dependencies) DeepCopy

func (d Dependencies) DeepCopy() (Dependencies, error)

DeepCopy returns a deep copy of a Dependencies object. It should be called before modifying dependencies to avoid interfering with dependencies in other factories.

func (Dependencies) Get

func (d Dependencies) Get(key string, out interface{}) (err error)

Get gets a single dependency. It is recommended to use the `ToStruct` method instead, as it allows getting and validating dependencies in a single operation. `out` should be a pointer.

func (Dependencies) Set

func (d Dependencies) Set(key string, value interface{})

Set sets a dependency.

func (Dependencies) ToStruct

func (d Dependencies) ToStruct(out interface{}) error

ToStruct marshals this dependency map into a struct. A factory cannot know the required dependencies needed to create a specific object type. In order to allow an object type creation function to verify that it is being passed all the dependencies it requires, it can define a struct that specifies its required dependencies, and call this method on the Dependencies object it receives. `out` must be a pointer to a struct. If `out` implements the validate.Validator interface, the populated struct will be automatically validated.

Example ``` // ObjectDependencies defines the dependencies required to create Object using a factory creation function.

type ObjectDependencies struct {
    gz.Logger `validate:"required"`
}

// Defining this method will automatically validate that the received dependencies match the expected values

func (od *ObjectDependencies) Validate() error {
    return validate.DefaultStructValidator(od)
}

[...]

// Factory creation function

func([...], dependencies factory.Dependencies) [...] {
    objectDependencies := &ObjectDependencies{}
    // The dependencies.ToStruct call will populate objectDependencies.
    // It will also validate that all required fields are in place because ObjectDependencies has a Validate method
    // defined.
    if err := dependencies.ToStruct(objectDependencies); err != nil {
         [...] // Handle error
    }
    [...]
}

```

type Factory

type Factory interface {
	// New sets the `out` parameter to a new instance of the specific object type.
	// `out` should be a pointer to a value able to contain the expected type.
	New(cfg *Config, dependencies Dependencies, out interface{}) error
	// Register registers a new object type the factory can create.
	Register(objectType string, fn NewFunc) error
}

Factory instances objects of a specific type with a given configuration. A factory works by mapping an object type to a factory creation function (NewFunc).

Example

The `example` package has an `Exampler` interface, and three different implementations of it. A package `Factory` is defined to allow other packages to dynamically request `Exampler` implementations.

In order to allow the package factory to create `Exampler` implementations, each implementation must define and register a factory creation function (NewFunc) in the package factory.

Define a factory creation function for each implementation that will be registered in the factory.

example/implementations/type1/example.go ```

func newType1(config interface{}, dependencies factory.Dependencies, out interface{}) error {
    // It is recommended to define a Config struct for your factory creation function.
    var typeConfig *Config
    if err := factory.SetValueAndValidate(&typeConfig, config); err != nil {
        return err
    }

    // Parse dependencies
    // It is recommended to define a Config struct for your factory creation function.
    var typeDependencies Dependencies
    if err := dependencies.ToStruct(&typeDependencies); err != nil {
        return err
    }

    // Initialize the implementation
    t1 := [...]

    // Set the the output value to the newly created instance
	   factory.SetValue(out, t1)
}

```

Create a package factory and register all implementations.

example/factory.go ``` package example

const (

// Implementation types
Type1 = "type1"
Type2 = "type2"
Type3 = "type3"

)

var Factory := factorymap.Map{
    Type1: type1New,
    Type2: type2New,
    Type3: type3New,
}

```

The package factory can now be used by other packages that need `Exampler`s.

consumer/consumer.go ```

func Example() error {
    // Prepare the factory config
    // This config is loaded manually here, but it can also be loaded from a file
    config := &factory.Config{
         Type: example.Type1,
         Config: [...],
    }

    // Prepare factory dependencies
    dependencies := Dependencies{ [...] },

    // Create a new `Exampler` object
    var exampler example.Exampler
    err := example.Factory.New(config, dependencies, &exampler)
    if err != nil {
        return err
    }
}

```

type NewFunc

type NewFunc func(config interface{}, dependencies Dependencies, out interface{}) error

NewFunc is a factory creation function used by a factory to instance objects. Creation functions are in charge of processing the provided config, gathering dependencies, initializing any additional subcomponents or dependencies and returning a new object of the expected type.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL