Design mode I

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.

Tags: Java Python Go Design Pattern

Posted by lewisstevens1 on Sun, 17 Apr 2022 18:14:33 +0930