The gof Abstract Factory Design Pattern in C #
-- Matthew mongoran
Part I. Abstract Factory Overview
Part1. abstract factory model Overview
The abstract factory is a gof (Gang of Four) creational pattern where the intent is "... provide an interface for creating families of related or dependent objects without specifying their concrete classes ". ("design patterns" -- gamma, help, Johnson, vlissides)
Abstract Factory mode is a creation mode with the intention of "providing an interface for creating a series of related or mutually dependent objects without specifying their specific classes ". (Design Patterns gof)
There are four main parts to any abstract factory:
- Abstract Factory: defines generic interface for creation of objects.
- Concrete Factory: Implementation of the abstract factory.
- Abstract product: the generic interface that defines the object to be created.
- Concrete Product: The implementation of the abstract product. In other words, the actual objects.
Any abstract factory consists of the following four parts:
- Abstract Factory: provides general interfaces for object creation.
- Specific Factory: Implementation of abstract factory.
- Abstract product: defines the general interface of the created object.
- Specific product: the implementation of the abstract product, that is, the actual object.
When the abstract factory is ready for consumption, we will be coding to the abstract members: the abstract factory and the abstract product. as a general rule, if our code base is abstract it shoshould be abstract all the way. maintenance can be a nightmare if we have concrete implementations for interfacing with some code and abstract classes and interfaces for other parts of the Code (how wocould we Then keep track of which is which and manage change ?). The actual implementation will exist in the concrete factory and the concrete product.
Once we made up our mind to use the abstract factory model, we began to write abstract members: Abstract factories and abstract products. As a general principle, if the basic code is abstract, it should always be abstract. If part of our code is used to implement a specific interface, and the other part of the code is an abstract class and an interface (how do we track which one is and manage changes ), maintenance will become a nightmare. The actual implementation will exist in specific factories and products.
The abstract factory can be implemented either through abstract base classes or interfaces. I often stand on the "interface soapbox" because it is often the best way to keep the code base flexible and have some structure at the same time. however, sometimes we don't want the rigidity that comes with a framework defined through interfaces, and so go with the alternative which is to use abstract base classes. such is the case with the provider pattern used extensively in. NET 2.0 Framework, which is basically a retriable Implementation of the abstract factory pattern. (but this is a subject for another article .)
If you have not seen it already, here's a short article I wrote on interface development.
Abstract Factory can implement both the self-abstract base class and the Self-interface. I prefer interfaces because the basic code is usually structured and flexible. However, sometimes we do not want to be bound by the framework defined by the interface, but turn to abstract base classes. This involves the factory method mode that is widely used in. NET 2.0. It is essentially a configurable Abstract Factory mode. (This is the topic of my other article)
If you are not quite clear, please refer to my article on interface development.
Part II. Implementation: an abstract automobile factory.
Part2. implementation: an abstract automobile factory.
Loosely based on an article at Wikipedia on the modelt, We'll be implementing an abstract factory to build automobiles. (http://en.wikipedia.org/wiki/Ford_Model_T) I'll be taking quite a few liberties and so all of you "car people" out there will probably be wincing with my lack of automobile knowledge, but please remember, the point here is our factory, not the actual cars we make.
Based on a compilation of a Wikipedia article on modelt, we will implement a factory for making cars. (Http://en.wikipedia.org/wiki/Ford_Model_T) I will be a little casual, so those "Car experts" may laugh at me for lack of car knowledge, but remember that the key here is our factory, not the car in real life.
To get started, we'll look at a car in terms of four key areas: the automobile body, engine, susion Sion, and transmission. These are the definitions for our abstract products.
At the core of everything is our iauto interface which defines a (very) Generic automobile.
In the beginning, we will consider the four key parts of a car: the main body, the engine, the brake system and the drive. The following is the definition of our abstract product.
All the core iauto interfaces, which define a (very) General car.
// The automobile -----------------------
Interface iauto
{
Iautobody body {Get ;}
Iautoengine engine {Get ;}
Iautosuspension suspension {Get ;}
Iautotransmission transmission {Get ;}
Void set (iautobody body );
Void set (iautoengine engine );
Void set (iautosuspension suspension );
Void set (iautotransmission transmission );
}
Next we have definitions for each of the parts:
// The Body ----------------------------------------
Enum bodytype
{
Car,
Convertable,
Sedan,
Coupe,
Truck
}
// The engine -----------------------
// The suspension ---------------------
// The transmission ----------------------
Enum drivetype
{
Frontwheeldrive,
Rearwheeldrive
}
Enum transmissiontype
{
Manual,
Automatic
}
Finally, we'll build our definition for the abstract factory.
Finally, we will define the abstract factory.
Interface iautofactory
{
Iauto getauto ();
Iautobody createbody ();
Iautoengine createengine ();
Iautosuspension createsuspension ();
Iautotransmission createtransmission ();
}
Part III. Implementation: The concrete products.
Part3. implementation: specific products.
For our Model T, we need concrete definitions for the automobile and each of the parts: the engine, body, transmission and suspension.
For modelt, we need to define the specific automobile and its various parts: the main body, engine, brake system and transmission device.
Here is the concrete implementation of the automobile. i'm keeping it as simple as possible here, but in real life there might be all sorts of methods and properties specific to the Model T. we are only going to implement things at the bare minimum.
Here is the specific definition of automobile. I will try to make it as simple as possible, although in real life modelt may have a lot of methods and attributes. We only implement things in a small way.
Keep in mind we are stripping out all the complexity that wocould exist in a real project and as you look through these, imagine what it wocould look like if, in the interface definition, there were five more properties and a dozen or so Methods outlining how all the parts of the automobile interact and you can get an idea of why we wocould use an abstract factory for construction of multiple similar complex objects.
Remember, we will remove all the complexities that exist in one actual project. Imagine that, in an interface definition, there are five or more attributes, a dozen or more methods, describing the relationship between all parts of the car, you will understand why we use abstract factories to create a large number of similar complex objects.
// Concrete automobile ----------------------------
Now for the definitions of the concrete components of the Model T. We'll keep these as simple as possible for the purposes of this article.
Next is the definition of each part of modelt. We will make this article as simple as possible.
// Concrete engine -----------------------------------------
// Concrete Body ---------------------------------
// Concrete Suspension ----------------------------------------------
// Concrete transmission ---------------------------
Part IV. Implementation: The concrete factory.
Part4. implementation: specific factory.
Finally, we need to implement the concrete factory. notice that I have implemented the interface methods using the "virtual" keyword. this is intentional, so when we want to make a new type of modeltfactory where there is a minor change in the Model T, we can inherit from this class and make the tweaks without having to re-write the whole factory.
Finally, we need to implement a specific factory. Note that I use the keyword "virtual" when implementing the interface method ". In this case, when we want to implement a new modelfactory because of a very small change, we can implement this transformation through inheritance without rewriting the entire factory.
Class modeltfactory: iautofactory
{
# Region iautofactory members
Public iauto getauto ()
{
Return new modelt ();
}
Public Virtual iautobody createbody ()
{
Return new modeltbody (500, bodytype. Car, 2, false );
}
Public Virtual iautoengine createengine ()
{
Return new modeltengine (450, 2, 35,100, 10, "hand crank ");
}
Public Virtual iautosuspension createsuspension ()
{
Return new modeltsuspension (150, 99, 56,
"Transversely mounted semi-elliptical spring ",
"Foot pedal applied band around Drum ");
}
Public Virtual iautotransmission createtransmission ()
{
Return new modelttransmission (100, drivetype. frontwheeldrive,
2, 2, transmissiontype. manual );
}
# Endregion
}
Part V. A builder.
Part5. a producer
Now that we 've covered all the bases (no pun intended), we'll create automobiles with our abstract factory using a builder method. in a more complex scenario, the builder may possibly be responsible for wiring all the different objects together if they required it. note: The builder is not a part of the pattern definition, but it makes life much easier, so it is here.
Now we have implemented all the foundations (no dual-off), and we will use a manufacturing method to produce cars through abstract factories. In a more complex scenario, manufacturing may be responsible for all objects as needed. Note: The Creator is not part of the schema definition, but it makes life easier.
Static class automobilebuilder
{
Public static iauto build (iautofactory factory)
{
Iauto myauto = factory. getauto ();
Myauto. Set (factory. createbody ());
Myauto. Set (factory. createengine ());
Myauto. Set (factory. createsusion Sion ());
Myauto. Set (factory. createtransmission ());
Return myauto;
}
}
Part VI. Implementing the factory.
Part6. implement factory.
After all the headache of creating the factory, it is actually a piece of cake to use. Check it out: to build a Model T, you only have...
After the headache of creating a factory, it is easy to use. To create a modelt, you only need:
// Build a Model T
Iautofactory factory = new modeltfactory ();
Iauto auto = automobilebuilder. Build (factory );
Now, where it really shines, is when we have a new version of the Model T.
Now, if we have a new modelt, it will be nice.
In the Wiki article it mentions that we can get deeper tread for the "Southern road model" so we only have to override our model T factory's createsuspension () method and we have a new vehicle coming from our factory (Notice I also gave it "Anti-Lock" breaks in addition to having a tread depth of 60... I know... anti-lock breaking systems weren't around und then, but what's the fun in writing articles if you can't take some liberties every now and then ).
As mentioned in that Wikipedia, we only need to override the createsupension () method of the modelt factory to get the "Southern road model ", in this way, I got a new transport from this factory.
Class southernroadmodeltfactory: modeltfactory
{
Public override iautosuspension createsuspension ()
{
Return new modeltsuspension (150, 99, 60,
"Transversely mounted semi-elliptical spring ",
"Anti-Lock ");
}
}
Not only can we adjust what kind of Model T is produced, but we can take advantage of our abstract factory to build any type of automobile: trucks, modern racing cars, anything you can think.
We can not only adjust the modelt to produce, but also use abstract factories to produce different cars: trucks, racing cars, and all kinds of cars you can think.
Hopefully this article helped you understand the basics of the abstract factory pattern.
I hope this article will help you understand the basics of the abstract factory model.
Until next time,
Happy Coding