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.