Documentation ¶
Index ¶
- Variables
- func CallFactories(factoryCalls Calls) error
- func ErrorWithContext(err error) error
- func SetValue(out interface{}, value interface{}) error
- func SetValueAndValidate(out interface{}, value interface{}) error
- type Call
- type Calls
- type Config
- type ConfigValues
- type Dependencies
- type Factory
- type NewFunc
Constants ¶
This section is empty.
Variables ¶
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 ¶
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 ¶
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 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.