Home >Java >javaTutorial >Summary of the seven principles of design patterns

Summary of the seven principles of design patterns

坏嘻嘻
坏嘻嘻Original
2018-09-14 09:45:021702browse

This tutorial will explain the concept of design patterns to you step by step through Java examples.

1. Single Responsibility Principle

Purpose: Reduce code complexity, system decoupling, and improve readability

Meaning: For a class, there is only one reason for the change of the class; the responsibility of the class is unique, and this responsibility is the only reason for the change of other classes.

Solution: Encapsulate different responsibilities into different classes or modules. When there are new requirements that divide existing responsibilities into smaller-granularity responsibilities, the existing code should be refactored in a timely manner. When the system logic is simple enough, the methods are few enough, the subclasses are few enough, or the subsequent associations are few enough, you don’t have to strictly follow your SRP principles to avoid over-design and excessive granularity.

Example:Wire type Wire supplies power to residents with a voltage of 220v; however, new demands increase and wires also transport high-voltage electricity with a voltage of 200kv. The original wire type can be implemented by adding methods Expansion, which violates the single responsibility principle. You can provide a base class and create two derived classes, residential power supply lines and high-voltage transmission lines.

2. Liskov Substitution Principle

Purpose: To prevent the system inheritance system from being destroyed

Meaning:All places that reference a base class must be able to transparently use objects of its subclasses.

Solution: Subclasses can implement abstract methods of the parent class, but cannot override non-abstract methods of the parent class; subclasses can add their own unique methods; when subclasses override or implement When the method of the parent class is a method, the preconditions of the method (i.e. the formal parameters of the method) are looser than the input parameters of the parent class method; when the method of the subclass implements the abstract method of the parent class, the postconditions of the method (i.e. the method return value) is more strict than the parent class. If the subclass cannot fully implement the methods of the parent class, or some methods of the parent class have been distorted in the subclass, it is recommended to disconnect the inheritance relationship and use dependency, aggregation, combination and other relationships instead of inheritance.

Example: The method for birds to fly with two wings has been defined; the newly added ostrich cannot fly. If the method of the parent class is overridden, what is the method for flying with two wings? If you don't do it, it will violate the Richter substitution principle and cause all birds to be unable to fly. Two basic bird classes should be created side by side, flying and flightless. The preconditions are looser and the postconditions are stricter. For example, the parent class returns Map and the subclass returns HashMap; the parent class accepts HashMap formal parameters and the subclass accepts Map.

3. Dependence Inversion Principle

Purpose: Avoid excessive maintenance work caused by demand changes

Meaning: High-level modules should not depend on low-level modules, both should rely on their abstractions; abstractions should not depend on details; details should depend on abstractions.

Solution: Interface-oriented programming, use interfaces or abstract classes to formulate specifications and contracts without involving any specific operations, and leave the task of showing details to their implementation classes Finish.

Example: The mother class Mother has a storytelling method TellStory, which relies on a Book class input and uses the getContent method of the Book class to tell stories. Then next time you need your mother to tell stories from newspapers or mobile phones, the original interface will be powerless. At this time, an IReader base class containing the getContent method is abstracted, and Book, Newspaper, and Cellphone are implemented separately. The mother's TellStory method accepts an IReader instance and calls the getContent method.

4. Interface Segregation Principle

Purpose: Avoid bloated interfaces

Meaning: Client It should not rely on interfaces that it does not need. The dependence of one class on another class should be based on the smallest interface.

Solution: Refine the interface appropriately and split the bloated interface into several independent interfaces.

Example:Examination interface, including methods to test language, mathematics, physics, chemistry, biology, politics, history, geography, etc. The student class implements the exam interface and takes the exam. The liberal arts student class and the science student class are derived from the student class. When implementing the exam interface, they need to implement some methods that they do not need (because liberal arts students do not take the physics and chemistry exam, and science students do not take the political, history, and geography exam). At this time, the examination interface needs to be refined and divided into basic subject examination interface, liberal arts examination interface and science examination interface; student class implements basic subject examination interface; liberal arts students and science students respectively implement liberal arts examination interface and science examination interface.

5. Demeter Principle

Purpose: Reduce the coupling between classes

Meaning: Each software unit has minimal knowledge of other units, and is limited to those software units that are closely related to its own unit.

Solution: Unfamiliar classes that do not have coupling relationships such as dependency, association, combination, aggregation, etc. should not appear inside the class as local variables.

Example: The principal manages the teachers, and the teachers manage the students. When the principal needs to call everyone, he should first call the teachers. However, it is not necessary to obtain the students' information and call the rolls through the teachers. Instead, the teachers should be allowed to manage the roll call of the students. Otherwise, unnecessary coupling will occur between the principal and the students. When the student class changes, both the teacher class and the principal class must be modified.

6. Composite Reuse Principle

Purpose: Prevent the class system from being huge

Meaning: When extending the functionality of a class, give preference to composition/aggregation over inheritance.

Solution: When the relationship between classes is "Is-A", use inheritance; when the relationship between classes is "Has-A", use combination.

Example:For example, in bridge mode, abstraction and implementation can be changed independently. When extending functions, just add implementation classes; for example, in decoration mode, only one class is needed to form a class. Classes extend new functionality. For graphics display requirements, use the graphics Shape class and the display Paint class to implement them. Each Shape class has a Paint class pointer responsible for graphics drawing and display. The Paint class derives the RedPaint class and the BluePaint class, and passes them to the Shape class to realize the drawing of graphics in different colors, so that the graphics drawing logic and graphics drawing implementation can be changed independently. One day the demand increases and all drawings need to add borders. You can add the PaintDecorator class, which is derived from the Paint base class. Each PaintDecorator class has a Paint object pointer. Add the virtual function AddedPaint, rewrite the Paint drawing method, and add the call to the AddedPaint method. . Add the BorderPaintDecorator class, which is derived from the PaintDecorator class, overrides the AddedPaint method, and adds the code to draw the border. In this way, adding a new class can expand the functions of all original brush classes.

7. Open Close Principle

Purpose: Improve scalability and facilitate maintenance

Meaning: Open for extension, closed for modification. That is, system expansion is encouraged, but modification of existing system code is not supported. In other words, when the software has new requirements and changes, it is only necessary to extend the software framework to adapt to the new requirements, rather than modifying the code within the framework.

Solution: The first 6 principles of design patterns and the 23 design patterns are well followed, and the opening and closing principle is naturally followed well. By remaining forward-looking and foreseeable about changes in requirements, the abstraction can be made more widely applicable, and the designed software architecture can be relatively stable. Variable details in software requirements are extended by deriving implementation classes from abstractions.

Attachment: Example code of synthetic reuse principle, using bridge mode and decoration mode in combination

#include <iostream>

//绘制类
class Paint
{
public:
	virtual void Draw() = 0;
};

//红色绘制类
class RedPaint : public Paint
{
public:
	void Draw()
	{
		std::cout << "Color Red!" << std::endl;
	}
};

//蓝色绘制类
class BluePaint : public Paint
{
public:
	void Draw()
	{
		std::cout << "Color Blue!" << std::endl;
	}
};

//图形类,使用桥接模式,将图形绘制逻辑与绘制实现解耦
class Shape
{
public:
	Shape(Paint* pt) : m_pPt(pt)
	{	 
	}

	virtual void Show()
	{
		std::cout << "Shape Style:" << std::endl;
		m_pPt->Draw();
	}

protected:
	Paint* m_pPt;
};


//长方形类
class Rectangle : public Shape
{
public:
	Rectangle(Paint* pt) : Shape(pt)
	{
	}
};

//圆形类
class Circle : public Shape
{
public:
	Circle(Paint* pt) : Shape(pt)
	{

	}
};

//附加绘制类,使用装饰模式,对原有绘制类进行功能扩展
class PaintDecorator : public Paint
{
public:
	PaintDecorator(Paint* pt) : m_pPt(pt) { }
	
	void Draw()
	{
		m_pPt->Draw();
		AddedPaint();
	}
	virtual void AddedPaint() = 0;

protected:
	Paint* m_pPt;
};

//附加边框类,对绘制类添加边框绘制功能
class BoarderDecorator : public PaintDecorator
{
public:
	BoarderDecorator(Paint* pt) : PaintDecorator(pt)
	{
	}

	void AddedPaint()
	{
		std::cout << "With Boarder!" << std::endl;
	}
};

void main()
{
	Shape* pShape = new Circle(new BoarderDecorator(new RedPaint()));
	pShape->Show();

	return;
}

Related recommendations:

JavaScript design pattern factory pattern and structure Device pattern_javascript skills

Initial exploration of JavaScript design patterns_javascript skills

The above is the detailed content of Summary of the seven principles of design patterns. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn