This article mainly introduces the example of using the factory method mode of Python design mode programming. It also analyzes the roles involved in the FactoryMethod mode, for more information, see the factory method mode, which is further abstract and promoted by the simple factory mode. it not only keeps the advantages of the simple factory mode, but also hides the class instantiation process from the customer, in addition, polymorphism is used to overcome the disadvantages that the factory class is too complex and not easy to expand. In the factory method mode, the factory category in the core position is no longer responsible for the creation of all products, but the specific creation work is handed over to the child class for completion. The core factory class in the factory method mode becomes an abstract factory role after being abstracted by functions. it is only responsible for providing the interfaces that must be implemented by specific factory subclass, it does not involve the details about which product class should be instantiated. The general structure of the factory method mode is shown in. to simplify the figure, only one product class and one factory class are provided. However, in actual systems, multiple product classes and multiple factory classes are usually designed.
The essence of the factory method mode is to delay object creation to its subclass implementation, that is, the subclass dynamically determines which product class should be instantiated according to the current situation. The factory method model involves four participants: Abstract factory role, specific factory role, abstract product role, and specific product role.
- The abstract Factory (Creator) role is the core of the factory method model. it defines the Factory method for creating abstract product objects. Abstract factory cannot be called directly by the outside, but any factory class used to create product objects in the pattern must implement the Factory method defined by it.
- The Concrete Creator is an external interface of the factory method mode. it is responsible for implementing the internal logic of creating specific product objects. The specific factory is closely related to the application and can be directly called by the outside world to create the desired product.
- The abstract Product role is the parent class of all objects created in the factory method mode. it describes the common interfaces of all specific products.
- The role of a specific Product is the creation target of the factory method mode. all created objects are instances of a specific class that acts as the role.
The abstract factory role declares the factory method to "produce" abstract products. The following is the demo Python code of the Abstract factory:
Creator. py
Class Creator:
"Abstract factory role """
# Create an abstract Product Factory method def factoryMethod (self): pass
A specific factory role is responsible for creating an instance of a specific product and returning it to the caller. A specific factory is related to a specific product. a common practice for implementation is to define a specific factory for each specific product. The following is the demo Python code for a specific factory:
Concretecreator. py
Class ConcreteCreator (Creator ):
"Specific factory roles """
# Factory method for creating a specific product def factoryMethod (self): product = ConcreteProduct () return product
The main purpose of abstract product roles is to provide a common interface for all specific products. Generally, you only need to give the corresponding declaration instead of specific implementation. The following is the demo Python code for abstract product classes:
Product. py
Class Product:
"Abstract product role """
# Def interface (self): pass
A specific product role serves as the final creation goal. generally, it is a subclass of the abstract product class and implements all factory methods defined in the abstract product class. in actual application, it usually has complicated business logic. The following is the demo Python code for a specific product class:
Concreteproduct. py
Class ConcreteProduct (Product ):
"Specific product roles """
# Public interface implementation def interface (self): print "Concrete Product Method"
When using the factory method mode, you usually need to introduce another client role to create a specific Factory object, and then call the Factory method in the factory object to create the corresponding product object. The following is the demo Python code of the client:
Client. py
Class Client:
"Client role """
Def run (self): creator = ConcreteCreator () product = creator. factoryMethod () product. interface () # main function if (_ name _ = "_ main _"): client = Client () client. run ()
In this simple schematic implementation, there is only one class that acts as a specific product and a specific factory, but in actual application, generally, there are multiple specific product classes at the same time. at this time, multiple specific factory classes need to be provided accordingly, and each specific factory is responsible for producing the corresponding specific product.
As shown in the activity sequence of the factory method mode, the Client first creates the ConcreteCreator object, and then calls the Factory method factoryMethod () of the ConcreteCreator object to "produce" the required ConcreteProduct object.
Here is a specific case:
If you open a Pizza store (PizzaStore abstract class) and sell Pizza sub-classes of various flavors, you need to prepare the corresponding Pizza (create a Pizza object) according to the customer's requirements ), then baking, slicing, and packaging;
The simplest way is to create a corresponding Pizza object in PizzaStore according to the customer's requirements (type determination), and then call the baking, slicing, and packaging methods of Pizza itself (implemented by the Pizza abstract class;
However, such code is not flexible, because you allow an abstract class to depend on specific objects. we can create a factory to produce Pizza, and return different Pizza objects based on different input types, that is, the code of the created object is moved to the factory from PizzaStore. But this is just a programming technique, not a computing mode.
In the factory method mode, we define an abstract interface (create_pizza) in PizzaStore as an abstract factory, while order_pizza is its customer, and place the creation of Pizza object in the PizzaStore subclass to solve the problem.
Currently, two Pizza stores, Cheese and Clam, and NY and Chicago, have different tastes for the same Pizza-they have improved to cater to local tastes, mainly from different raw materials, therefore, we implement four Pizza types (NYStyleCheesePizza, NYStyleClamPizza, mixer, and chicagstyleclampizza). each type uses different raw material combinations and creates different objects based on the customer's city and style. based on the factory method, we put the code created by the object into the PizzaStore subclass for implementation.
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 self.toppings: print " %s" % n def bake(self): print "Bake for 25 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 def 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" sefl.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.sauce = "NY Sauce" self.toppings.append("NY toopping A") self.toppings.append("NY toopping B") class ChicagoStyleClamPizza(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 NYStyleCheesePizza() elif pizza_type == "clam": return NYStyleClamPizza() else: return None class ChicagoPizzaStore(PizzaStore): def create_pizza(self, pizza_type): if pizza_type == "cheese": return ChicagoStyleCheesePizza() elif pizza_type == "clam": return ChicagoStyleClamPizza() else: 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 toopping B Bake for 25 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 NY toopping B Chicago toopping A Bake for 25 minutes at 350. Cutting into square slices. Put into official box. John ordered a Chicago Style Clam Pizza.