The factory method pattern is a further abstraction and generalization of the simple factory model, which not only preserves the advantages of simple Factory mode to hide the instantiation process of the class from the customer, but also overcomes the shortcomings of the factory class being too complex and not easy to expand through polymorphism. In the factory method model, the factory class at the core is no longer responsible for all product creation, but rather to the sub-class to complete the specific creation work. The core factory class in the factory method pattern, after functional abstraction, becomes an abstract factory role that is only responsible for giving the interface that a specific factory subclass must implement, without involving the details of which product class should be instantiated. The general structure of the factory method pattern is shown in the figure, in order to simplify only a product class and a factory class are given, but in the actual system it is often necessary to design multiple product classes and multiple factory classes.
The essence of a factory method pattern is to defer the creation of an object to its subclass implementation, where the subclass dynamically determines which product class should be instantiated, depending on the current situation. As can be seen, the factory approach model involves four participants in abstract factory roles, specific factory roles, abstract product roles, and specific product roles.
- The abstract Factory (Creator) role is at the heart of the factory method pattern and is responsible for defining the factory methods that create abstract product objects. Abstract factories cannot be called directly by the outside world, but any factory class used to create product objects in a pattern must implement the factory method defined by it.
- The specific factory (concrete Creator) role is the external interface of the factory method pattern, which is responsible for implementing the internal logic that creates the specific Product object. Specific factories and applications are closely related, can be directly called by the outside world to create the required products.
- The abstract product role is the parent of all objects created by the factory method pattern, and it is responsible for describing common interfaces common to all specific products.
- The concrete product role is the creation target of the factory method pattern, and all created objects are instances of a specific class that acts as the role.
Abstract factory roles are responsible for declaring factory methods (Factory method), which are used to "produce" abstract products, and the following is an example Python code for an abstract factory:
creator.py
Class Creator:
"" "Abstract Factory Role" "
# Factory method for creating abstract products def factorymethod (self): Pass
The specific factory role is responsible for creating an instance of a specific product and returning it to the caller. The specific factory is related to the specific products, the implementation of the common practice is to define a specific factory for each specific product. The following is an example Python code for a specific factory:
concretecreator.py
Class Concretecreator (Creator):
"" "Specific Factory Role" ""
# Create a factory method for a specific product def factorymethod (self): Product = concreteproduct () return product
The primary purpose of the abstract product role is to provide a common interface for all specific products, usually by simply giving the corresponding declaration, rather than giving a specific implementation. The following is an example Python code for an abstract product class:
product.py
Class Product:
"" "Abstract Product Role" ""
# Common interface for all product Classes Def interface (self): Pass
The specific product role acts as the ultimate goal of creation, generally it is a subclass of abstract product classes, implements all the factory methods defined in the abstract product class, and usually has more complex business logic when applied. The following is an example Python code for a specific product class:
concreteproduct.py
Class Concreteproduct (Product):
"" "Specific product Role" ""
# Implementation of the public Interface Def interface (self): print "Concrete Product Method"
When you apply the factory method pattern, you typically also need to introduce a client role, which is responsible for creating the specific factory object, and then invoking the factory method in the factory object to create the corresponding Product object. The following is a sample Python code for the client:
client.py
Class Client:
"" Client Role "" "
def run (self): Creator = Concretecreator () Product = Creator.factorymethod () product.interface () # main function if (__name__ = = "__ma in__ "): Client = Client () Client.run ()
In this simple schematic implementation, there is only one class that acts as a specific product and a specific factory role, but in real-world applications, it is common to have multiple specific product classes at the same time, where the corresponding need to provide a number of specific factory classes, each specific factory is responsible for the production of specific products.
The activity sequence of the factory method pattern, as shown, is that the client clients first create the Concretecreator object and then call the factory method of the Concretecreator object FactoryMethod (), which is responsible for "production" The desired Concreteproduct object.
Below we look at a specific case:
If you open a pizza store (Pizzastore abstract class) sell various flavors of pizza (pizza subclass), then you need to prepare the corresponding pizza (create pizza object) according to customer requirements, and then bake, Slice, packaging;
The simplest approach is to create the appropriate pizza object in Pizzastore based on the customer's requirements (type judgment) and then invoke the bake, slice, and wrap method of pizza itself (implemented by the pizza Abstract class);
But the code lacks elasticity, Because you have an abstract class that relies on specific objects, we can create a factory to produce pizza, return different pizza objects based on the different types of values passed in, i.e. move the code that creates the object from Pizzastore to the factory. But it's just a programming trick, not a pattern.
in Factory method mode, we define an abstract interface (Create_pizza) as an abstract factory in Pizzastore, and Order_pizza is its customer, and the creation of the pizza object is placed in the Pizzastore subclass to resolve. The
existing cheese and clam two pizza, as well as the NY and Chicago two outlets, each with a different taste in the same pizza-to cater to local tastes, the main difference is from different raw materials So we implemented four pizza types (Nystylecheesepizza, Nystyleclampizza, Chicagostylecheesepizza, and Chicagostyleclampizza), Each uses a different mix of raw materials, according to the customer's city and choose the style we create different objects; According to the factory method, we put the object-created code into the Pizzastore subclass to implement.
Code:
#!/usr/bin/python Class Pizza:name = "" Dough = "" Sauce = "" toppings = [] def prepare (self): print "Preparing% S "% self.name print" dough:%s "% self.dough print" sauce:%s "% self.sauce print" Add toppings: "For N in Sel F.toppings:print "%s"% n def bake (self): print "Bake-minutes at 350." def cut (self): print "cutting into diagonal slices." def box (self): print "Put into official box." def get_name (self): Return Self.name class Pizzastore:def Order_pizza (Self, pizza_type): Self.pizza = Self.create_ Pizza (Pizza_type) Self.pizza.prepare () Self.pizza.bake () Self.pizza.cut () Self.pizza.box () return Self.pizza D EF Create_pizza (Self, pizza_type): Pass class Nystylecheesepizza (pizza): Def __init__ (self): Self.name = "NY Style" Cheese Pizza "Self.dough =" ny Dough "self.sauce =" ny Sauce "self.toppings.append (" NY toopping A ") self.toppings. Append ("NY toopping B") class Chicagostylecheesepizza (Pizza): Def __Init__ (self): Self.name = "Chicago Style Cheese Pizza" Self.dough = "Chicago dough" self.sauce = "Chicago sauce" s Efl.toppings.append ("Chicago toopping A") def Cut (self): print "cutting into square slices." Class Nystyleclampizza (Pizza): def __init__ (self): self.name = "NY Style Clam Pizza" Self.dough = "ny Dough" Self.s Auce = "NY Sauce" Self.toppings.append ("NY toopping A") self.toppings.append ("NY toopping B") class Chicagostyleclam Pizza (Pizza): def __init__ (self): Self.name = "Chicago Style Clam Pizza" Self.dough = "Chicago dough" self.sauce = "Chicago Sauce" Self.toppings.append ("Chicago toopping A") def Cut (self): print "cutting into square slices." Class Nypizzastore (Pizzastore): Def create_pizza (self, pizza_type): if Pizza_type = = "Cheese": return nystylecheesep Izza () elif Pizza_type = = "Clam": Return Nystyleclampizza () Else:return None class Chicagopizzastore (Pizzasto RE): Def Create_pizza (self, pizza_type): if PizzA_type = = "Cheese": Return Chicagostylecheesepizza () elif Pizza_type = = "Clam": Return Chicagostyleclampizza () E Lse:return None If __name__ = = "__main__": Ny_store = Nypizzastore () Chicago_store = Chicagopizzastore () pizza = Ny_store.order_pizza ("cheese") print "Mike ordered a%s."% Pizza.get_name () Print pizza = Chicago_store.order_pizza (" Clam ") print" John ordered a%s. "% Pizza.get_name () print
Output:
Preparing NY Style Cheese Pizza dough:ny dough sauce:ny sauce Add toppings: NY toopping A NY tooppin G B Bake for minutes at 350. Cutting into diagonal slices. Put into official box. Mike ordered a NY Style Cheese Pizza. Preparing Chicago Style Clam Pizza dough:chicago dough sauce:chicago sauce Add toppings: NY toopping a< C10/>ny toopping B