1 design mode
1 strategy mode
Policy mode:
Design an interface for a function that can be changed
A series of implementation classes are extended for the interface, and the unique characteristics of the object are given when the object is generated
Separate the implementation of functions from objects and separate objects and behaviors to reduce coupling and improve code reuse
If a duck yard is simulated, there are green headed ducks and red headed ducks At first, each duck had its own members and methods, but with the increase of the number of ducks There are too many classes to maintain the design, so consider creating a duck parent class using inheritance All duck subclasses inherit it and optionally override the methods in the parent class But as the system becomes bloated, when you need to change a method in the parent class Methods in thousands of subclasses also need to be overridden, and inheritance affects the whole body Therefore, the flight, chirp and other behaviors can be made into interfaces, and various implementation classes can be made for these interfaces The parent class takes these interfaces as members, and the child class selectively instantiates the implementation classes of these interfaces to complete different functions And can pass set Method to replace the function
2 observer mode
Observer mode:
The roles in the system are divided into topics and observers. Observers work with topics. Topics can publish data so that all observers can get the same data to get a cleaner design. Swing and many GUI frameworks use observer mode a lot
Referring to the working mode of the newspaper, the observer mode is equal to the publishing house+subscriber The publishing house manages all subscribers and publishes information to all its subscribers whenever it needs to publish information Two interfaces can be designed to complete observer mode ISpeaker and IListener,ISpeaker As a theme, IListener As an observer ISpeaker The abstract methods are addOneListener,removeOneListener,speakMessage IListener The abstract methods are readMessage The class as the subject implements ISpeaker Maintain one after the interface List<IListener> Whenever information is published speakMessage Polling when List Call all observers readMessage that will do The subject does not know any information about the observer. It does not lie in what the observer is or what he is doing The observer does not know the specific implementation of the topic. It only lies in the messages from the topic, which is loose coupling The above behavior of publishing messages from the topic to the observer can be regarded as the push of the topic to the observer At the same time, the subject object can also be directly sent to the observer, which can be used by the observer himself get The data in the topic to actively pull information
3 decorator mode
Decorator mode:
The decorated person and the decorator belong to the same type. The decorated person is regarded as a member of the decorator. The process of decoration is to take the decorated person as a parameter of the decorator, generate a new decorator, and take the object as a member to expand the function through combination, Java IO is full of decorator mode
When designing a coffee shop menu, you can initially design a category for each drink However, with the increase of drinks, more and more kinds are needed, and there are also large cups, small cups, sugar, milk and other needs If you design a class for each demand, such as large coffee with sugar, small latte with sugar and milk Then it will appear in the system"Explosion like",Too many classes need to be maintained Therefore, the decorator mode can be adopted, and the basic drinks can be used as"Decorated person",Take a large cup, add sugar, etc"Decorator" They have a common parent"Material Science",Make the decorator a member of the decorator When you need a small cup of sugar and milk latte, create a latte object first Then use the small cup as a parameter"decorate",The obtained object is decorated with sugar...
Example:
public class Tea extends Beverage { public Tea() { super("Tea"); } @Override public double cost() { return 10; } } public class Milk extends Decorator { private Beverage beverage; public Milk(Beverage beverage) { super("milk"); this.beverage = beverage; } @Override public double cost() { return 3 + beverage.cost(); } @Override public String getDescription() { return beverage.getDescription() + " + Milk"; } } eg: Tea tea = new Tea(); tea = new Milk(tea); // Decorated with milk tea = new Mocha(tea); // Decorated with mocha tea = new BigCup(tea); // Decorated with large cups Got a big cup of tea with milk and mocha
java. Decorator mode in io:
FileInputStream inputStream = new FileInputStream(""); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
4 factory mode
Factory mode:
When a large number of objects are created in a class, the more objects, the more fragile the class is. If a dependency is modified slightly, the whole class cannot work normally. Therefore, it is necessary to separate the function implementation from the object creation process, encapsulate the object creation process, decouple the program, and separate the function implementation from the object creation to reduce the dependency
Factory mode can be divided into simple factory and factory method The simple factory provides a method or static method for producing the corresponding object, and the return value is this kind of object Put the object creation process into the method of another class public static Pizza createPizza(String type) { Pizza pizza = null; if("cheese".equals(type)) { pizza = new CheesePizza(); } else if("clam".equals(type)) { pizza = new ClamPizza(); } else { return null; } return pizza; } The factory method defines an abstract class to create an object, delaying the process of creating an object to a subclass When a subclass tries to get an object from the factory, the concrete production object is implemented by the abstract method completed in the subclass public abstract class PizzaStore { public Pizza getPizza(String type) { Pizza pizza; pizza = createPizza(type); return pizza; } protected abstract Pizza createPizza(String type); }
5 singleton mode
Singleton mode:
Sometimes only one object is needed in the whole application, such as registry, log and thread pool. If these objects are created arbitrarily without constraints, it will lead to abnormal program behavior and unexpected results. The singleton mode ensures that there is only one instance of a class and provides a global access point
Singleton mode is often used to manage shared unique resources Normal singleton mode: public class Registry { private static Registry instance; private Registry() {} public static Registry getInstance() { if(instance == null) { instance = new Registry(); } return instance; } } Synchronous singleton mode under multithreading: public class Registry { private volatile static Registry registry; private Registry() {} public static Registry getInstance() { if(registry == null) { synchronized (Registry.class) { if(registry == null) { return new Registry(); } } } return registry; } } The above two singletons are created in lazy mode That is, reproduction when acquisition is needed, the hungry man mode can also be used However, if there are a large number of objects created by hungry man mode, it will give users a bad experience when the application is started
6 command mode
Command mode:
Through the command mode, methods can be encapsulated and actions can be encapsulated into command objects, so that they can be stored, transmitted and called at will. The command mode decouples the object issuing the request from the object executing the request
In the process of designing a remote controller, the remote controller can control the switch of TV and table lamp When the design mode is not adopted, objects such as TV and table lamp are encapsulated into the remote control object The switching method of remote controller is packaged with the switching method of TV and table lamp Such a design first creates dependencies, and functions are coupled with objects If you use command mode, design a Command Interface, which contains an abstract method execute() For this Command The interface implements different command objects, such as light on object and light off object Specific objects are encapsulated in the light on object and light off object Light,The specific function implementation is completed by the command object Use the combination of the interface as the caller(Remote control)Members of, through set To replace the command object When the caller makes this call, the method in the command object is called The command object will complete specific operations in the future, so as to decouple the object issuing the request from the object executing the request
7 adapter mode
Adapter mode:
Convert the interface of a class into another interface expected
The adapter pattern makes it easy for incompatible classes to cooperate
When one interface is needed to realize multiple functions, the adapter mode is adopted stay JDK of swing In technology, listeners are usually added to various components, such as focus acquisition/lose /*The numbered text box gets the focus, and all the numbered text boxes are selected*/ this.jtxtId.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { jtxtId.selectAll(); } }); /*The name text box gets the focus, and all the name text boxes are selected*/ this.jtxtName.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { jtxtName.selectAll(); } }); FocusAdapter Is an adapter that implements FocusListener Interface Here, the specific implementation method is given to the user to rewrite the method to use according to the scenario The function can be decoupled from the implementation through the adapter pattern, and different adapters can be replaced through combination And the adapter can be empty and implemented by the user
8 template method mode
Template method mode:
The skeleton of an algorithm is defined in a method, and some steps are delayed to subclasses. The template method can enable subclasses to redefine some steps in the algorithm without changing the structure of the algorithm framework
That is, there is a template method containing several abstract methods in the parent class, and different subclasses inherit the parent class and implement different abstract methods The template method has different functions In the process of making coffee and tea tea: 1,Bring the water to a boil -> 2,Brew tea with boiling water -> 3,Pour the tea into the cup -> 4,Add lemon Coffee: 1,Bring the water to a boil -> 2,Brew coffee with boiling water -> 3,Pour the coffee into the cup -> 4,Add sugar and milk We can simply make each step into a method and put it in a specific place Tea and Coffee In class However, this leads to the coupling between function and implementation, and it is found that the first step and the third step are the same. Therefore, the template method pattern can be adopted public abstract class Drink { public Drink() {} public final void prepare() { boilWater(); brew(); pourInCup(); add(); } public abstract void brew(); public abstract void add(); public void boilWater() { System.out.println("Bring the water to a boil"); } public void pourInCup() { System.out.println("Pour it into the cup"); } } public class Tea extends Drink { public Tea() {} @Override public void brew() { System.out.println("Brew tea with boiling water"); } @Override public void add() { System.out.println("Add lemon"); } } When called Tea Medium prepare()Method is actually called Drink Class prepare()method here prepare()Method is a template method, which will be executed in turn boilWater() brew() pourInCup() add() Because it is Tea Invoked prepare() Therefore, the abstract method in the template method is selected Tea Medium brew()and add() Some steps are delayed to subclasses to decouple the function from the implementation At the same time, it can also be added in the template method hook() To control the process of template methods, such as: public abstract class Drink { public Drink() {} public final void prepare() { boilWater(); brew(); pourInCup(); //Hook point if(wantAddSomething()) { add(); } } public abstract void brew(); public abstract void add(); public void boilWater() { System.out.println("Bring the water to a boil"); } public void pourInCup() { System.out.println("Pour it into the cup"); } //hook can be overridden by subclasses to control template methods public boolean wantAddSomething() { return true; } } Subclasses can override hook(),That is, the above wantAddSomething()To control the flow of template methods hook()It can affect the process of template methods and enable subclasses to control the trend of template methods
In Java Arrays. In util The sort () method can sort. For simple Integer type arrays, you can sort directly, but you can also let a class implement compareTo() in the Comparable interface to specify the sorting conditions you want. In this process, sort() can be regarded as a template method and compareTo() can be regarded as a link in the template method, The user implementation changes the result of the final template method execution
9 status mode
Status mode:
Allows an object to change its behavior when its internal state changes
When designing a candy machine, the candy machine has different states If no coin is inserted, coin has been inserted, shipment in progress, refund medium status If the design pattern is not adopted, it needs to be carried out continuously in multiple methods if-else Judge the current state, such as: public void insertMoney() { if(this.state == NO_MONEY) { System.out.println("Coin paid"); this.state = HAS_MONEY; System.out.println("Please click <purchase> or <refund> Button"); return; } else if(this.state == HAS_MONEY) { this.state = BACK_MONEY; System.out.println("Please don't put in coins continuously. Your coins will be withdrawn immediately"); backMoney(); return; } } Although it can be easily completed, once new requirements are added, such as winning requirements Most of the code of the whole machine has to be rewritten. The previous practice violates the opening and closing principle, and the system is not flexible and logical confusion Now use the state pattern to design and define a State Interface, each state of the candy machine implements this State Interface Delegate the action of the candy machine to the state class public class Machine { private State soldOutState; private State noMoneyState; private State hasMoneyState; private State soldState; private State state; private int count = 0; public Machine(int count) { this.soldOutState = new SoldOutState(this); this.noMoneyState = new NoMoneyState(this); this.hasMoneyState = new HasMoneyState(this); this.soldState = new SoldState(this); this.count = count; if(count > 0) { this.state = noMoneyState; } } // Status interface public interface State { //coin-operated void insertMoney(); //refund void ejectMoney(); //Turn the crank void turnCrank(); //Distribute candy void dispense(); } // The state of the candy machine when there is no money to put into the machine public class NoMoneyState implements State { private Machine machine; public NoMoneyState(Machine machine) { this.machine = machine; } @Override public void insertMoney() { System.out.println("You put in a coin"); machine.setState(machine.getHasMoneyState()); } @Override public void ejectMoney() { System.out.println("No coin has been inserted and cannot be refunded"); } @Override public void turnCrank() { System.out.println("No coin has been inserted, unable to turn the crank"); } @Override public void dispense() { System.out.println("No coin has been inserted, unable to get candy"); } } This is a two-way combination process. Various state classes are combined into the candy machine, and the candy machine is combined into the state class Various behaviors of the candy machine are executed by the state class. After the state class works, it will call the candy machine to enter the next state
10 agent mode
Proxy mode:
Provide an "Avatar" for an object to control access to that object
The proxy pattern provides a substitute for a real object when a method in the proxy is called Proxy objects delegate processing to real objects, but before and after delegation More functions can be added, such as permission detection, security judgment and remote call... Thus, the function of real objects is expanded non invasively and real objects are protected There are many application scenarios for agents, such as Firewall agent: Control the access of network resources to avoid illegal operations Cache agent: It provides temporary storage for expensive calculation results, and allows multiple customers to share the results to reduce calculation Synchronization agent: Provide secure access to real objects in a multithreaded environment ...
2 design principles
2.1 distinguish between change and invariance
The change of one part of the system will not affect other parts, so as to reduce the change caused by code change and make the system more flexible
Find out where changes may be needed in the application and separate them Don't put it with code that doesn't need to change
2.2 multi use combination and less inheritance
Use inheritance as little as possible and treat interfaces as members to extend the functionality of classes
Inheritance can obtain the code of the parent class to complete code reuse But inheritance also compresses the space for subclass changes, and if the parent class wants to make changes Then all subclasses will be affected
2.3 loose coupling
The two objects are loosely coupled, and they can still interact, but they don't know each other's details
Loose coupling can make two objects unclear, not in each other's specific implementation It can also complete the data interaction and improve the flexibility of the system
2.4 opening and closing principle
Classes should be developed for extensions and closed for modifications
The program should be free from change and good at expansion On the basis of trying not to modify the source code, you can match the new behavior
2.5 Dependency Inversion Principle
When an object is instantiated directly, it depends on its specific implementation class. This dependence should be minimized
Do not let high-level components rely on low-level components, and both high-level and low-level components should rely on"abstract" Parent classes and interfaces are abstractions Like in a pizza shop, if you let PizzaStore Direct dependence on various CheesePizza,BeefPizza That is, high-level components depend on low-level components whole PizzaStore A large number of dependent implementation classes, so you can PizzaStore Dependent parent Pizza,Make all kinds of pizza Pizza Subclass of To follow the dependency inversion principle and separate the function from the creation object
2.6 principle of minimum knowledge
Don't couple too many classes together
Don't couple too many classes together, so as not to modify one part of the system and affect other parts If many classes depend on each other, the system is a fragile system and needs more energy to maintain
2.7 Hollywood principles
Don't call me, I'll call you
Hollywood principle can reduce the dependence between objects For example, in a bad system, high-level components rely on low-level components, and low-level components rely on side components The side components depend on low-level components, and the whole system is seriously coupled The Hollywood principle allows low-level components to hook themselves to the system, and high-level components decide how and when to use these low-level components As in the template method Coffee and Drink In, execute coffee.prepare()Time Drink It's a high-level component, Coffee It is a low-level component that executes coffee.prepare()When, yes Drink Called Coffee Methods in instead of Drink Depend on Coffee In order to reduce dependency
2.8 principle of single responsibility
Each class is only responsible for its own business, and a class is only responsible for one job
Following the principle of single responsibility can improve the readability of classes and the maintainability of the system When modifying a function, it can significantly reduce the impact on other functions. It is designed according to the function by module