Design pattern learning day2

Posted by airric on Sat, 08 Jan 2022 15:04:57 +0100

Factory mode

extraction

Scene introduction

Look at a pizza project: it should be convenient for the expansion of pizza types and maintenance

1. There are many kinds of pizza (such as greenpizza, CheesePizz, etc.)

2. Pizza making includes prepare, bake, cut and box

3. Complete the pizza shop ordering function.

(1) Pizza's parent abstract class

//Abstract the Pizza class
public abstract class Pizza {
	protected String name; //name
	//The raw materials are different for different pizza, so we make it into an abstract method
	public abstract void prepare();
	public void bake() {System.out.println(name + " baking;");}
	public void cut() {System.out.println(name + " cutting;");}
	//pack
	public void box() {System.out.println(name + " boxing;");}
	public void setName(String name) {this.name = name;}
}

(2) Order pizza

public class OrderPizza {
	// constructor 
	public OrderPizza() {
		Pizza pizza = null;
		String orderType; // Type of pizza ordered
		do {
			orderType = getType();
			if (orderType.equals("greek")) {
				pizza = new GreekPizza();
				pizza.setName(" Greek pizza ");
			} else if (orderType.equals("cheese")) {
				pizza = new CheesePizza();
				pizza.setName(" Cheese pizza ");
			} else {
				break;
			}
			//Output pizza production process
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
			
		} while (true);
	}
   	private String getType() {//A private inner class used to get the kind of pizza the user wants
		try {
			BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("input pizza type:");
			String str = strin.readLine();
			return str;
		} catch (IOException e) {
			e.printStackTrace();
			return "";
		}
	}
}

(3) Cheese pizza, Greek pizza, etc

Directly inherit the parent pizza class:

public class CheesePizza extends Pizza {
	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println(" Prepare raw materials for making cheese pizza ");
	}
}

Greek pizza

public class GreekPizza extends Pizza {
	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println(" Prepare raw materials for Greek pizza ");
	}
}

(4) Pizza store class, equivalent to a client

//It is equivalent to a client and sends out a subscription
public class PizzaStore {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new OrderPizza();
	}
}

The above is programming with common ideas

Advantages and disadvantages of common mode

1. The advantages are easy to understand, simple and easy to operate.

2. The disadvantage is that it violates the ocp principle of design pattern, that is, it is open to extension and closed to modification. That is, when we add new functions to the class, we try not to modify the code or modify the code as little as possible.

3. For example, if we want to add a new Pizza (Pepper Pizza), we need to make the following modifications:

Simple factory mode

Analysis: it is acceptable to modify the code, but if we also have the code to create Pizza in other places, it means that we also need to modify it, and the code to create Pizza often has many places.

Idea: encapsulate the created Pizza object into a class, so that when we have a new Pizza type, we only need to modify the class, and other codes that create Pizza objects do not need to be modified. - > Simple factory mode. Just take any subclass of Pizza you want from the factory. Don't contact privately.

introduce

1. The simple factory mode belongs to the creation mode, which is a kind of factory mode. The simple factory pattern is a factory object that determines which product class instance to create. The simple factory pattern is the simplest and most practical pattern in the factory pattern family

2. Simple factory pattern: defines a class for creating objects, which encapsulates the behavior (code) of instantiating objects

3. In software development, when we will use a lot of to create a certain object, a certain class or a batch of objects, we will use the factory mode

Code improvement

Design scheme of simple factory pattern: define a class that can instantiate Pizza objects and encapsulate the code to create objects.

//Simple factory class
public class SimpleFactory {
	//The orderType returns the corresponding Pizza object
	//Simple factory mode is also called static factory mode. This static method can directly pass the class name Method name
	public static Pizza createPizza2(String orderType) {
		Pizza pizza = null;
		System.out.println("Use simple factory mode 2");
		if (orderType.equals("greek")) {
			pizza = new GreekPizza();
			pizza.setName(" Greek pizza ");
		} else if (orderType.equals("cheese")) {
			pizza = new CheesePizza();
			pizza.setName(" Cheese pizza ");
		} else if (orderType.equals("pepper")) {
			pizza = new PepperPizza();
			pizza.setName("Pepper pizza");
		}
		return pizza;
	}
}

orederpizza can be changed to the following form:

public class OrderPizza2 {
	Pizza pizza = null;
	String orderType = "";
	// constructor 
	public OrderPizza2() {
		do {
			orderType = getType();
			pizza = SimpleFactory.createPizza2(orderType);//Here, you can call the static method directly
			// Output pizza
			if (pizza != null) { // Order succeeded
				pizza.prepare();
				pizza.bake();
				pizza.cut();
				pizza.box();
			} else {
				System.out.println(" Failed to order pizza ");
				break;
			}
		} while (true);
	}
	// Write a method to get the type of pizza customers want to order
	private String getType() {
		try {
			BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("input pizza type:");
			String str = strin.readLine();
			return str;
		} catch (IOException e) {
			e.printStackTrace();
			return "";
		}
	}
}

You can directly call new orderpizza 2 in the client.

Factory method model

The core idea is to delay the creation of special classes until the subclass is initialized.

Scene: new demand of pizza project: when ordering pizza, customers can order pizza with different flavors, such as cheese pizza in Beijing, pepper pizza in Beijing, cheese pizza in London and pepper pizza in London.

introduce

Factory method pattern design scheme: abstract the instantiation function of pizza project into abstract methods and implement them in different taste ordering subclasses.

Factory method pattern: defines an abstract method to create an object, and the subclass determines the class to be instantiated. The factory method pattern defers instantiation of objects to subclasses.

code

Key parts:

OrderPizza class

public abstract class OrderPizza {
	//Define an abstract method, createPizza, and let each factory subclass implement it by itself
	abstract Pizza createPizza(String orderType);
	// constructor 
	public OrderPizza() {
		Pizza pizza = null;
		String orderType; // Type of pizza ordered
		do {
			orderType = getType();
			pizza = createPizza(orderType); //Abstract method, which is completed by the factory subclass
			//Output pizza production process
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
			
		} while (true);
	}
	// Write a method to get the type of pizza customers want to order
	private String getType() {
		try {
			BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("input pizza type:");
			String str = strin.readLine();
			return str;
		} catch (IOException e) {
			e.printStackTrace();
			return "";
		}
	}
}

BJOrderPizza class:

public class BJOrderPizza extends OrderPizza {
	@Override
	Pizza createPizza(String orderType) {	
		Pizza pizza = null;
		if(orderType.equals("cheese")) {
			pizza = new BJCheesePizza();
		} else if (orderType.equals("pepper")) {
			pizza = new BJPepperPizza();
		}
		// TODO Auto-generated method stub
		return pizza;
	}
}

LDOrderPizza class:

public class LDOrderPizza extends OrderPizza {
	@Override
	Pizza createPizza(String orderType) {
		Pizza pizza = null;
		if(orderType.equals("cheese")) {
			pizza = new LDCheesePizza();
		} else if (orderType.equals("pepper")) {
			pizza = new LDPepperPizza();
		}
		// TODO Auto-generated method stub
		return pizza;
	}
}

Store client class:

public class PizzaStore {
	public static void main(String[] args) {
		String loc = "bj";//By making input here, you can create different flavors of pizza according to the user's choice
		if (loc.equals("bj")) {
			//Create all kinds of Pizza with Beijing flavor
			new BJOrderPizza();
		} else {
			//Create a variety of pizzas with London flavors
			new LDOrderPizza();
		}
		// TODO Auto-generated method stub
	}
}

Abstract factory pattern

Basic introduction

1. Abstract Factory Pattern: an interface is defined to create related or dependent object clusters without specifying specific classes

2. Abstract factory pattern can integrate simple factory pattern and factory method pattern.

3. From the design level, the abstract factory pattern is an improvement (or further abstraction) of the simple factory pattern.

4. Abstract the factory into two layers, absfactory (Abstract Factory) and the factory subclass of concrete implementation. Programmers can use the corresponding factory subclasses according to the type of object they create. This turns a single simple factory class into a factory cluster, which is more conducive to code maintenance and expansion.

5. Class diagram:

code

1.AbsFactory

//Abstract layer (Interface) of an abstract factory pattern
public interface AbsFactory {
	//Let the following factory subclass implement it
	public Pizza createPizza(String orderType);
}

2.BJFactory

//This is a factory subclass
public class BJFactory implements AbsFactory {
	@Override
	public Pizza createPizza(String orderType) {
		Pizza pizza = null;
		if(orderType.equals("cheese")) {
			pizza = new BJCheesePizza();
		} else if (orderType.equals("pepper")){
			pizza = new BJPepperPizza();
		}
		return pizza;
	}
}

3.LDFactory

public class LDFactory implements AbsFactory {
	@Override
	public Pizza createPizza(String orderType) {
		Pizza pizza = null;
		if (orderType.equals("cheese")) {
			pizza = new LDCheesePizza();
		} else if (orderType.equals("pepper")) {
			pizza = new LDPepperPizza();
		}
		return pizza;
	}
}

4.OrderPizza

public class OrderPizza {
	AbsFactory factory;
	// constructor 
	public OrderPizza(AbsFactory factory) {setFactory(factory);}
	private void setFactory(AbsFactory factory) {
		Pizza pizza = null;
		String orderType = ""; // User input
		this.factory = factory;
		do {
			orderType = getType();
			// Factory may be a factory subclass in Beijing or a factory subclass in London
			pizza = factory.createPizza(orderType);
			if (pizza != null) { // Order ok
				pizza.prepare();
				pizza.bake();
				pizza.cut();
				pizza.box();
			} else {
				System.out.println("Subscription failed");
				break;
			}
		} while (true);
	}
	// Write a method to get the type of pizza customers want to order
	private String getType() {
		try {
			BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("input pizza type:");
			String str = strin.readLine();
			return str;
		} catch (IOException e) {
			e.printStackTrace();
			return "";
		}
	}
}

5.PizzaStore

public class PizzaStore {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//new OrderPizza(new BJFactory());
		new OrderPizza(new LDFactory());
	}
}

Application of factory mode in JDK calendar

Summary of plant mode

1. Significance of factory mode: extract the code of instantiated object and put it into a class for unified management and maintenance, so as to decouple the dependency relationship with the main project. So as to improve the expansibility and maintainability of the project.

2. Three factory modes (simple factory mode, factory method mode and abstract factory mode)

3. Dependency abstraction principle of design pattern

  • When creating an object instance, do not directly the new class, but put the action of the new class in a factory method and return. Some books say that variables do not directly hold references to specific classes.
  • Do not let classes inherit concrete classes, but inherit abstract classes or implement interfaces
  • Do not override methods already implemented in the base class.

Topics: Design Pattern