A simple factory
The "if Else" or "switch case" statements that are responsible for creating different classes depending on the situation in the code make up a simple factory, which is the production of a simple factory dedicated to the class.
For example, head first cited pizza example, with samplepizzafactory responsible for the customer's choice to create Chesspizza, Greekpizza and other different kinds of pizza.
classsamplefactory{ PublicPizza Createpizza (stringtype) {Pizza Pizza; if(Type = ="Chesspizza") {Pizza=NewChesspizza (); } Else if(Type = ="Greekpizza") {Pizza=NewGreekpizza (); } Else { Throw NewException (); } returnPizza; } }
UML is as follows:
Passing the type here is the customer's decision-making process.
The simple factory model is strictly not a design pattern, but a programming habit, but it is a habit to adopt, and the follow-up factory pattern and abstract Factory mode code implementation details are inseparable from this programming habit.
Two factory models
The factory pattern defines an interface for creating objects, but subclasses decide which class to instantiate. The factory method defers the instantiation of the class to the subclass.
It is also an example of pizza, because people in different regions have different tastes, the same chesspizza in different areas, such as New York's Pizzastore offers pancakes, cheese less chesspizza, but Chicago's Pizzastore offers thick cakes , the Chesspizza of cheese, the same Greekpizza and other pizza also have regional differences.
In order to deal with this situation, we can let Newyorkpizzastore and Chicagopizzastore inherit the unified Pizzastore, and the parent class Pizzastore in addition to the Orderpizza method, It also adds the abstract method Createpizza,pizzastore as a specification exists at the same time, can be used for subclasses to implement in different ways, thus satisfying the regional differences of pizza.
The code is as follows:
//various Pizza Public Abstract classPizza { Public stringname; Public voidPrepare () {Console.WriteLine ("Preparing"+name); Console.WriteLine ("tossing Dough"); Console.WriteLine ("Adding sauce"); } Public voidBake () {Console.WriteLine ("Baking"); } Public voidCut () {Console.WriteLine ("Cut"); } } classNychesspizza:pizza { PublicNychesspizza () {name="Nychesspizza"; } } classChicagochesspizza:pizza { PublicChicagochesspizza () {name="Chicagochesspizza"; } } classNyclampizza:pizza { PublicNyclampizza () {name="Nyclampizza"; } } classChicagoclampizza:pizza { PublicChicagoclampizza () {name="Chicagoclampizza"; } }//Pizzastore Public Abstract classPizzastore { PublicPizza Orderpizza (stringtype) {Pizza Pizza; Pizza=Createpizza (type); Pizza. Prepare (); Pizza. Bake (); Pizza. Cut (); returnPizza; } protected AbstractPizza Createpizza (stringtype); } Public classNypizzastore:pizzastore {protected OverridePizza Createpizza (stringtype) {Pizza Pizza; Switch(type) { Case "Chess": Pizza=NewNychesspizza (); Break; Case "Clam": Pizza=NewNyclampizza (); Break; default: Throw NewException (); } returnPizza; } } Public classChicagopizzastore:pizzastore {protected OverridePizza Createpizza (stringtype) {Pizza Pizza; Switch(type) { Case "Chess": Pizza=NewChicagochesspizza (); Break; Case "Clam": Pizza=NewChicagoclampizza (); Break; default: Throw NewException (); } returnPizza; } } //Calling codePizzastore PS=NewNypizzastore ();p S. Orderpizza ("Chess");
UML Class Diagrams:
With Factory mode, the Pizzastore and pizza classes are polymorphic, and different factories and different pizza species can be combined at will. On the other hand, pizzastore in addition to the Createpizza method and Orderpizza method, Createpizza method has regional differences, need quilt class rewrite, but the rest of the method can be in different regions Pizzastore Universal, This increases the reuse of the code. These common methods do not have to know exactly which area of the pizzastore production of the pizza, which is called the factory method pattern definition, "the subclass determines which class to instantiate."
Reliance leads to principle
Dependency inversion Principle to rely on abstraction, do not rely on specific classes.
Headfirst mentioned this sounds similar to "programming for interfaces, not programming for implementation", which is even more confusing by this point. However, depending on the emphasis on the dependency of the interface, relying on the principle in addition to the interface dependency, more emphasis on the relationship between the layers, this need to deepen the experience.
In the case of pizza, Pizzastore is a high-level component, and the pizza is the underlying component. According to the general idea will be pizzastore depends on the specific pizza class, because pizzastore to get specific pizza class and provide to the customer. The structure would be like this:
This extremely dependent structure is a nightmare for maintenance because any pizza specific class changes can cause changes in pizzastore, and there may be new pizza types to join. (think of the code that you wrote, which is this type: ( )
If you follow the dependency inversion principle, you can extract pizza abstract class from Newyorkchesspizza, Chicagogreekpizza, Pizza abstract class contains pizza common methods and properties, and let subclasses override Createpizza this method. Pizzastore only need to know pizza this abstract class, whether it is the new pizza type or change the original pizza practice, as long as they inherit pizza, according to the specification of pizza abstract class, can be included in the nature of the system, Can be sold by Pizzastore.
Below, the underlying pizza concrete class relies on a higher layer of pizza abstract class.
The principle of dependency inversion is well applied in simple Factory mode and Factory mode. The simple factory pattern did an abstraction, while the factory pattern did two abstractions (pizza abstract class and Pizzastore abstract Class).
Avoid violating the dependency inversion principle
Headfirst gives the following recommendations:
A variable cannot hold a reference to a specific class;
Do not allow classes to derive from specific classes;
Do not overwrite methods that have been implemented in the base class.
Three abstract Factory
Definition: Abstract Factory mode provides an interface for creating a family of related or dependent objects without explicitly specifying a specific class.
To the abstract factory this piece, was headfirst the example of the halo, and sometimes pizza is pizza conditioning, and later combined with the example of a big talk in the db to understand, the original headfirst in the light seasoning this piece is a self-contained abstract factory example.
The concrete structure is this:
There are many kinds of sauce and chess, NewYork Pizza use a combination of spices, Chicago pizza use another seasoning combination. Beginner design mode, pizza add seasoning so really bad understanding ah, if with pizza shop pizza and pasta will be more appropriate point.
In the case of pizza seasoning, use the seasoning factory pizzaingredientfactory to create the seasoning "family" required by pizza. In the specific code, the interface programming is decoupled from the actual seasoning plant and the pizza raw material, which makes it easy to create a family of raw materials for different pizza needs.
The code is as follows:
//spices chess and sauce Public Abstract classSauce {} Public classmarinarasauce:sauce{ PublicMarinarasauce () {Console.WriteLine ("Ingredient Marinarasauce"); }} Public classbruschettasauce:sauce{ PublicBruschettasauce () {Console.WriteLine ("Ingredient Bruschettasauce"); }} Public Abstract classChess {} Public classreggianochess:chess{ Publicreggianochess () {Console.WriteLine ("Ingredient reggianochess"); }} Public classgoatchess:chess{ Publicgoatchess () {Console.WriteLine ("Ingredient goatchess"); }}//Seasoning FactoryInterfacepizzaingredientfactory {Sauce createsauce (); Chess createchess (); } Public classNypizzaingredientfacotry:pizzaingredientfactory { PublicSauce createsauce () {return Newmarinarasauce (); } PublicChess createchess () {return Newreggianochess (); } } Public classChicagopizzaingredientfacotry:pizzaingredientfactory { PublicSauce createsauce () {return Newbruschettasauce (); } PublicChess createchess () {return Newgoatchess (); } }//Calling codepizzaingredientfactory PIF=Newchicagopizzaingredientfacotry ();p If. Createchess ();p If. Createsauce ();
Personal understanding: Abstract Factory is based on the factory model, for example, in the case of pizza seasoning, the Factory mode can handle a seasoning, but the treatment of a variety of spices, that is, the seasoning family, it is necessary to use the abstract factory. So the abstract factory is built on a higher level of abstraction than the factory model, and the interior of the abstract factory is the factory model.
5 simple factories, factories, abstract factories