-
Notifications
You must be signed in to change notification settings - Fork 0
Abstract factory

Creational pattern.
Provides an interface, that is responsible for creation of family of related objects. On image above, interface AbstractFactory has two methods:
- createProductA() : AbstractProductA
- createProductB() : AbstractProductB
As you can see, products, that are created by AbstractFactory interface, are hidden behind their interfaces as well. In such scenario, Client class, that uses AbstractFactory interface is not linked to any particular implementation of an interface AbstractProductA or AbstractProductB.
Concrete factories produce concrete products, i.e. ConcreteFactory1 produces ProductA1 and ProductB1 on corresponding method calls. Such concrete factories take responsibility to produce logically valid and compatible combinations of products, such as
ProductA1 + ProductB1
ProductA2 + ProductB2
But not the
ProductA1 - ProductB2
Based on given example, it would be invalid to use such combination, and as long our client uses abstract factory, it would be impossible for him to mix those up.
Advantages:
+ It is easy to add new family of related products in our system. (e.g. ConcreteFactory3 with ProductA3 and ProductB3)
+ Client code does not depend upon any concrete implementation, thus allowing us to reuse this code for any existing family of products with ease
+ Client code does not care about products compatibility, concrete factories do.
Note It is hard to add/remove support for new/existing product types. For example, if we add AbstractProductC - we need to modify all existing concrete factories in our system.
At this project we have the following model:
Abstract factory has two so-called "products":
1. Range - represents abstract range of values of some abstract type T.
-
IntegerRange - representing range of Integer values
-
LocalDateRange - representing range of LocalDate values
2. Selector - represents some logic for selecting value across given Range.
-
RandomIntegerSelector - selects random Integer value from given IntegerRange
-
RandomLocalDateSelector - selects random LocalDate value from given LocalDateRange
Thus, AbstractFactory interface has two methods:
- createRange(T from, T to) : T
- createSelector() : Selector< T >
And we have two implementations of this AbstractFactory
- RandomIntegerSelectorFactory - providing us with IntegerRange and RandomIntegerSelector
- RandomLocalDateSelectorFactory - providing us with LocalDateRange and RandomLocalDateSelector
These two concrete factories provide us with compatible and logically valid combination of Range and Selector objects. As it can be seen mixing these Ranges and Selectors, for example IntegerRange with RandomLocalDateSelector would lead to ClassCastExceptions at runtime.