1. Related concepts
Design pattern is a summary of previous code development experience. It is a series of methods to solve specific problems. It is not a syntax provision, but a set of solutions to improve code reusability, maintainability and readability.
1.1 six principles of design mode
General principle: Open Closed Principle
A software entity, such as class, template and function, is open to extension and closed to modification. That is, when the program needs to be expanded, it does not modify the original code, but expands the original code to achieve the effect of hot plug.
1. Single responsibility principle
Each class only implements a single responsibility, otherwise it should be broken down.
2. Liskov Substitution Principle
The methods of subclasses to parent classes need not be overridden and overloaded as much as possible.
3. Dependency Inversion Principle
In interface oriented programming, abstraction should not depend on concrete, but concrete should depend on abstraction.
4. Interface aggregation principle
There are no methods that subclasses cannot use but must implement in each interface, otherwise the interface should be split.
5. Law of Demeter
As long as there is a coupling relationship between classes, it is a friend relationship. Only communicate with direct friends. The less a class knows about its dependencies, the better. In this way, when the dependent class changes, it can minimize the impact on the class.
6. Composite Reuse Principle
Try to use object combination instead of inheritance relationship to achieve the purpose of software reuse.
1.2 three categories of design patterns
Creative pattern:
Factory mode, abstract factory mode, singleton mode, prototype mode, builder mode
Structural pattern:
Adapter mode, decorator mode, agent mode, appearance mode, bridge mode, combination mode, sharing mode
Behavioral pattern:
Policy mode, template method mode, observer mode, iterator mode, responsibility chain mode, command mode, memo mode, status mode, visitor mode, mediator mode and interpreter mode
2. Design mode
Here I summarize several familiar design patterns, which will be updated continuously.
2.1 creation mode
Singleton pattern:
One of the simplest design patterns, which involves a single class while ensuring that only a single object is created.
Application example: a school can only have one principal (principal)
package main import "sync" type Singleton struct { name string age int64 } var ( lazySingleton *Singleton once = &sync.Once{} ) // GetLazyInstance lazy func GetLazyInstance() *Singleton { if lazySingleton == nil { once.Do(func() { lazySingleton = &Singleton{} }) } return lazySingleton } // test func main() { GetLazyInstance() }
Factory pattern:
One of the common design patterns in Java. In this pattern, when creating objects, the creation logic will not be exposed to the user, but the specified objects will be created through an interface.
Application example: when a customer buys a car, it's ok to pick up the goods directly from the factory without knowing the specific manufacturing process of the car. Just go to the factory of the brand you need to pick up the car.
interface Car { void drive(); } //The Audi class implements the car interface, because the Audi is also a car that can be driven class Audi implements Car { public Audi(){ System.out.println("Produce an Audi"); } @Override public void drive() { System.out.println("Drive Audi"); } } //BMW class implements the car interface, because BMW is also a car and can certainly drive class Bmw implements Car{ public Bmw(){ System.out.println("Produce a BMW"); } @Override public void drive() { System.out.println("Drive a BMW"); } } //The factory that produces cars. The factory receives a car name. You just need to tell him what car you want to produce to produce the corresponding car class CarFactory { public static Car getCar(String caename){ if(caename.equals("audi")){ return new Audi(); }else if(caename.equals("bmw")){ return new Bmw(); }return null; } } //test class Test { public static void main(String[] args) { //Tell the factory that you need to produce an audi car, then pass a parameter audi to onta Car audi = CarFactory.getCar("audi"); //We can produce Audi cars and call the driving method to drive audi.drive(); //BMW similar Car bmw = CarFactory.getCar("bmw"); bmw.drive(); } }
2.2 structural mode
Decorator Pattern:
Allows you to add new functionality to an existing object without changing its structure.
Application example: decorator in python is a good application. Decorator is often used to record logs, performance tests, etc.
def clock(func): func_doc = func.__doc__ def clocked(*args): start = time.time() result = func(*args) end = time.time() print("{}Time consuming to complete{}second".format(func_doc,end-start)) return result return clocked @clock def test(): """Test function""" print('running...') time.sleep(3)
Bridge pattern:
Also known as interface pattern, it decouples abstraction and concretization, making them change independently.
Application example: the idea of interface programming is widely used in the design of go language, which can be described as interface oriented programming.
package main import "fmt" // usb interface type USB interface { run() } // Mouse structure type Mouse struct { } // The run method of usb is different for different structures func (this Mouse) run() { fmt.Println("mouse is running,please click it...") } // test func main(){ mouse := Mouse{} mouse.run() }
2.3 behavioral model
Strategy pattern:
The behavior of a class can be changed at run time. In the policy mode, create various policy objects and a context object whose behavior changes with the change of the policy object. The policy object changes the execution method of the context object.
Application example: Zhuge Liang's knapsack, each knapsack is a strategy.
package main import "fmt" //Now there is a prince. If he wants to have attack skills, the prince can choose weapons such as sword, axe and gun to attack, //And choose different attack strategies according to different existing tools type strategy interface{ attack() } type prince struct { name string wp strategy } func (pr *prince)beginAttack() { pr.wp.attack() } type sword struct { } func (sw *sword)attack() { fmt.Println("attack with a sword") } type axe struct { } func (ax *axe)attack() { fmt.Println("attack with a axe") } func main() { me := prince{"dashi", &sword{}} me.beginAttack() me.wp = &axe{} me.beginAttack() }
Iterator pattern:
Iterator pattern is a very common design pattern in Java. This pattern is used to access the elements of objects sequentially, and it does not need to know the underlying representation of collection objects.
Application example: iterator in Java
// Interface interface Iterator { boolean hasNext(); //Determine whether it is the last element Object next();//Returns the next element } // iterator class NameRepository { private Object names[]; public NameRepository(Object[] names) { this.names = names; } public Iterator getIterator() { return new NameIterator(); } private class NameIterator implements Iterator { private int index; @Override public boolean hasNext() { if(this.index < NameRepository.this.names.length){ return true; } return false; } @Override public Object next() { if(this.hasNext()){ return NameRepository.this.names[this.index++]; } return null; } } } // test class IteratorPatternDemo { public static void main(String[] args) { Object[] OBJ={"Robert" , "John" ,"Julie" , "Lora"}; NameRepository namesRepository = new NameRepository(OBJ); Iterator iter = namesRepository.getIterator(); while (iter.hasNext()){ String name = (String)iter.next(); System.out.println("Name : " + name); } } }
At the end of this article, I hope it will be helpful to you, and I will keep updating it later.