Instance
Simple factory Mode
A pizza store sells different pizza servers, including fruit pizza, cheese pizza, and vegetable pizza. Prepare, bake, cut, and box for each batch ). The pizza store needs to provide a variety of pizza servers for customers.First, check the batch SA category definition.abstract public class Pizza { String name; String dough; String sauce; ArrayList
toppings = new ArrayList
(); public String getName() { return name; } public void prepare() { System.out.println("Preparing " + name); } public void bake() { System.out.println("Baking " + name); } public void cut() { System.out.println("Cutting " + name); } public void box() { System.out.println("Boxing " + name); } public String toString() { // code to display pizza name and ingredients StringBuffer display = new StringBuffer(); display.append("---- " + name + " ----\n"); display.append(dough + "\n"); display.append(sauce + "\n"); for (int i = 0; i < toppings.size(); i++) { display.append(toppings.get(i) + "\n"); } return display.toString(); }}
There are some types of batch SA, which are inherited from the parent class to implement batch SA. Here we use an example to representpublic class CheesePizza extends Pizza { public CheesePizza() { name = "Cheese Pizza"; dough = "Regular Crust"; sauce = "Marinara Pizza Sauce"; toppings.add("Fresh Mozzarella"); toppings.add("Parmesan"); }}
The batch store is defined as (the batch store specializes in producing batch stores, but it cannot provide batch stores by itself and needs to be called by operators)public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(String type) { Pizza pizza; pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; }}
Defines an operator, that is, a simple factory class, through which a large number of batch operations can be produced.public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }}
The following class diagram shows the simple factory mode.Release/release/fF + sj4tcS0 + sLrz + C1sdPasPO2qNTaxfrI + release + LXqtcTX9reoyseyu8/release + release/ztcSzrMDgo6zTw8bky/release = "brush: java;">public abstract class PizzaStore { abstract Pizza createPizza(String item); public Pizza orderPizza(String type) { Pizza pizza = createPizza(type); System.out.println("--- Making a " + pizza.getName() + " ---"); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; }}
Pizza stores in other places inherit from superclasses: Each pizza store has its own production method.
public class NYPizzaStore extends PizzaStore { Pizza createPizza(String item) { if (item.equals("cheese")) { return new NYStyleCheesePizza(); } else if (item.equals("veggie")) { return new NYStyleVeggiePizza(); } else if (item.equals("clam")) { return new NYStyleClamPizza(); } else if (item.equals("pepperoni")) { return new NYStylePepperoniPizza(); } else return null; }}
public class ChicagoPizzaStore extends PizzaStore { Pizza createPizza(String item) { if (item.equals("cheese")) { return new ChicagoStyleCheesePizza(); } else if (item.equals("veggie")) { return new ChicagoStyleVeggiePizza(); } else if (item.equals("clam")) { return new ChicagoStyleClamPizza(); } else if (item.equals("pepperoni")) { return new ChicagoStylePepperoniPizza(); } else return null; }}
The relationship diagram of the batch store is as follows:
Let's look at the batch operation at this time. Because there are already many types of batch operations available, the same batch operation is different for batch stores in different places.import java.util.ArrayList;public abstract class Pizza { String name; String dough; String sauce; ArrayList
toppings = new ArrayList
(); void prepare() { System.out.println("Preparing " + name); System.out.println("Tossing dough..."); System.out.println("Adding sauce..."); System.out.println("Adding toppings: "); for (int i = 0; i < toppings.size(); i++) { System.out.println(" " + toppings.get(i)); } } void bake() { System.out.println("Bake for 25 minutes at 350"); } void cut() { System.out.println("Cutting the pizza into diagonal slices"); } void box() { System.out.println("Place pizza in official PizzaStore box"); } public String getName() { return name; } public String toString() { StringBuffer display = new StringBuffer(); display.append("---- " + name + " ----\n"); display.append(dough + "\n"); display.append(sauce + "\n"); for (int i = 0; i < toppings.size(); i++) { display.append((String) toppings.get(i) + "\n"); } return display.toString(); }}
Look at the different practices of the same cheese batchpublic class NYStyleCheesePizza extends Pizza { public NYStyleCheesePizza() { name = "NY Style Sauce and Cheese Pizza"; dough = "Thin Crust Dough"; sauce = "Marinara Sauce"; toppings.add("Grated Reggiano Cheese"); }}
public class ChicagoStyleCheesePizza extends Pizza { public ChicagoStyleCheesePizza() { name = "Chicago Style Deep Dish Cheese Pizza"; dough = "Extra Thick Crust Dough"; sauce = "Plum Tomato Sauce"; toppings.add("Shredded Mozzarella Cheese"); } void cut() { System.out.println("Cutting the pizza into square slices"); }}
How to call different batch SA processes in the factory mode:Public class PizzaTestDrive {public static void main (String [] args) {PizzaStore nyStore = new NYPizzaStore (); // first, define a Pizza store pizza Pizza = nyStore. orderPizza ("cheese"); // then, obtain a cheese batch System from the batch produced in the call shop. out. println ("Ethan ordered a" + pizza. getName () + "\ n"); PizzaStore Chicago store = new ChicagoPizzaStore (); // define another pizza store pizza = Chicago store. orderPizza ("cheese"); // get the cheese Batch System in the store. out. println ("Joel ordered a" + pizza. getName () + "\ n ");}}
In the factory model, it is obvious that factories (different batch stores) and products (different batch stores) are separated.For example:
Factory
Product
The factory method mode defines an interface for creating objects, but a subclass determines the class to be instantiated. The factory method delays the class Instantiation to the subclass.-Differences between the simple factory mode and the factory ModeIn a simple factory, everything is done in one place. However, the factory method is to create a framework and let the subclass decide how to implement it. For example, in the factory method, oreserPizza () methods provide a general framework to create a batch. The orderPizza () method depends on the factory method to create a specific class and create the actual batch. You can inherit the PizzaStore class to decide what the batch is actually made. Simple factory practices can encapsulate object creation. However, simple factories do not have the elasticity of factory methods, because simple factories cannot change the products being created.This reflects the essence of the factory model: dependency abstraction, not specific classes (dependency inversion principle)Several guidelines to prevent Dependency inversion principles from being violated during OO design
- 1-variables cannot hold references to specific classes
- 2-do not allow a class to be derived from a specific class
- 3-do not override the methods implemented in the base classBut the rules are dead, and they do not have to be fully followed. You can try
Abstract Factory Model
Then, in the above example, we have implemented the ability to create pizza from different places. Although the local production method is adopted in various regions, there is not a certain standard for the use of raw materials, that is to say, this may lead to different franchisees joining inferior raw materials, thus affecting reputation.Now, we need to adopt a unified raw material supply system.Note: The mushrooms used in Beijing's batch store may be different from those used in Shanghai store. In this way, the variety of raw materials in each place may be different.Beijing: mushroom, yellow cheese, small onion Shanghai: big mushroom, white cheese, big onion Shenzhen: flammulina velutipes, Sweet cheese, short onion
First, we define a raw material Interface for batch processing.
Public interface PizzaIngredientFactory {public Dough createDough (); // mushroom public Sauce createSauce (); // onion public Cheese createCheese (); // Cheese}
Then define the raw material factory in Beijing to implement the interface:Public class BJPizzaIngredientFactory implements PizzaIngredientFactory {public Dough createDough () {return new ThinCrustDough (); // small mushroom} public Sauce createSauce () {return new MarinaraSauce (); // small onion} public Cheese createCheese () {return new ReggianoCheese (); // yellow Cheese }}
Raw material example
public interface Dough { public String toString();}
public class ThinCrustDough implements Dough { public String toString() { return "Thin Crust Dough"; }}
In the same way, the raw material factory in other places can be implemented, and the code here will not be mentioned one by one.With the new raw materials, you can re-create a batch of authentic raw materials.Public abstract class Pizza {String name; Dough dough; // Three raw materials: Sauce sauce; Cheese cheese; abstract void prepare (); // The raw materials to be prepared before batch processing are different from the previous one because the raw materials are already the same. You need to re-implement void bake () {System. out. println ("Bake for 25 minutes at 350");} void cut () {System. out. println ("Cutting the pizza into diagonal slices");} void box () {System. out. println ("Place pizza in official PizzaStore box");} void setName (String Name) {this. name = name;} String getName () {return name;} public String toString () {StringBuffer result = new StringBuffer (); result. append ("----" + name + "---- \ n"); if (dough! = Null) {result. append (dough); result. append ("\ n");} if (sauce! = Null) {result. append (sauce); result. append ("\ n");} if (cheese! = Null) {result. append (cheese); result. append ("\ n");} return result. toString ();}}
The pizza super class is ready, so you can implement the cheese pizza.public class CheesePizza extends Pizza { PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } void prepare() { System.out.println("Preparing " + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); }}
After cheese pizza is done, you can make Beijing cheese pizza with Beijing yellow cheese raw materials. But before that, we need a Beijing pizza store, because the brand-new raw materials in Beijing are used here (which is different from the above), the Beijing pizza store is as follows:public class BJPizzaStore extends PizzaStore { protected Pizza createPizza(String item) { Pizza pizza = null; PizzaIngredientFactory ingredientFactory = new BJPizzaIngredientFactory(); if (item.equals("cheese")) { pizza = new CheesePizza(ingredientFactory); pizza.setName("BeiJIng Style Cheese Pizza"); } return pizza; }}
With this, you can place an order named Beijing cheese pizza.Public class PizzaTestDrive {public static void main (String [] args) {PizzaStore nyStore = new BJPizzaStore (); Pizza pizza = nyStore. orderPizza ("cheese"); // first call the parent class pizzastroe order method System. out. println ("Ethan ordered a" + pizza + "\ n ");}}
The class diagram is as follows:System flexibility.
The disadvantages of the simple factory model are as follows:
(1) because the factory class integrates the creation logic of all products, the entire system will be affected once it fails to work normally.
(2) using the simple factory mode will increase the number of classes in the system and increase the complexity and difficulty of understanding the system in a certain program.
(3) It is difficult to expand the system. Once a new product is added, the factory logic has to be modified. When there are many product types, the factory logic may be too complicated, which is not conducive to system expansion and maintenance.
(3) In simple factory mode, due to the use of static factory methods, factory roles cannot form a hierarchy based on inheritance.
-Factory Mode
- The factory method mode has the following advantages:
(1) In the factory method mode, the factory method is used to create the product required by the customer, and the details of the specific product category to be instantiated are also hidden to the customer, users only need to care about the factory corresponding to the product, no need to care about the creation details, or even the Class Name of the specific product category.
(2) the design of polymorphism Based on the factory role and Product role is the key to the factory method model. It allows the factory to determine which product object to create, and the details of how to create this object are completely encapsulated in a specific factory. The factory method mode is also called the multi-state factory mode because all specific factory classes have the same abstract parent class.
(3) Another advantage of using the factory method mode is that when adding a new product to the system, you do not need to modify the interfaces provided by the abstract factory and abstract product, and you do not need to modify the client, you do not need to modify other specific factories or products, but you only need to add a specific factory or product. In this way, the scalability of the system becomes very good, it fully complies with the "open and closed principles ".
The disadvantages of the factory method mode are as follows:
(1) When adding a new product, you need to write a new specific product class and provide the corresponding factory class. The number of classes in the system will increase in pairs, to some extent, the complexity of the system is increased, and more classes need to be compiled and run, which will bring additional overhead to the system.
(2) Considering the scalability of the system, the abstract layer needs to be introduced and defined using the abstract layer in client code, which increases the abstraction and difficulty of the system, DOM, reflection, and other technologies may be used to increase the difficulty of system implementation.
-Abstract Factory Mode
- Advantages:
(1) isolate the generation of specific classes so that users do not need to know what is created.
(2) When multiple objects in a product family are designed to work together, it ensures that the client always uses only objects in the same product family.
- Disadvantages:
(1) It is difficult to expand the abstract factory to produce new types of products when adding new product pairs.