SOLID -- OOP design principles
SOLID
https://team-coder.com/solid-principles/
OOP五原则,帮助开发者设计 可维护 和 可扩展的类。
SOLID is an acronym for five principles that help software developers design maintainable and extendable classes. It stands for Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion. The acronym was first introduced by Michael Feathers and is based on Uncle Bob’s paper Design Principles and Design Patterns.
This article is a summary of the SOLID principles as originally introduced by Uncle Bob. I explain each of the five principles with an example.
Single Responsibility Principle
类, 模块, 包 职责 明确。
不搞万能军刀。
Single Responsibility Principle
A class should have one, and only one, reason to change.
Every class is responsible for exactly one thing. That means it has only one reason to change. If you change anything in that class, it will effect only one particular behavior of the software. That makes the code more robust because there will be less side effects. If a class had two responsibilities and you changed anything, the risk would be high that you also break the logic for the second behavior.
Example
A
ScoreCounterclass is only responsible for counting the score of a game according to the scoring rules. This class should only change if the scoring rules change.
Open-Closed Principle
模块, 对修改封闭, 对扩展开放。
Open-Closed Principle
You should be able to extend a classes behavior, without modifying it.
The classes you use should be open for extension but closed for modification. This can be achieved with inheritance. You don’t have to touch the class you want to extend if you create a subclass of it. The original class is closed for modification but you can add custom code to your subclass to add new behavior.
Inheritance may be the most popular way to implement the Open-Closed Principle but it is not the only one. Objective-C, for example, offers categories which can be used to add methods to a class, without touching the original class and without subclassing it.
Example
Imagine you use an external library which contains a class
Car. TheCarhas a methodbrake. In its base implementation, this method only slows down the car but you also want to turn on the brake lights. You would create a subclass ofCarand override the methodbrake. After calling the original method of the super class, you can call your ownturnOnBrakeLightsmethod. This way you have extended theCar‘s behavior without touching the original class from the library.
Liskov Substitution Principle
子类 可以被 基类 替换。
即子类 需要 完全遵从 父类的定义, 不能修改其函数参数 以及 作用。
Liskov Substitution Principle
Derived classes must be substitutable for their base classes.
Assume we have a class
Bwhich is a subclass ofA. If your program works with an objectaof classAyou can replace it with an objectbof classBwithout changing the behavior of the program.The implementation of this principle can be a little bit tricky if you combine it with the Open-Closed Principle. Even if you extend the behavior of your class in a subclass, you must make sure that you could still exchange the base class with the derived class without breaking anything.
Example
You have an instance of the class
Carwhich your program uses to perform adriveaction. This instance could be replaced by an instance of the classTeslaifTeslais a subclass ofCar.
Interface Segregation Principle
接口隔离原则, 对于一个类, 不应该定义 多种业务接口, 例如一个类饲养员, 有喂狗的方法, 和喂猪的方法,
不应该将两个换在一个饲养员类上, 应该构造 狗饲养员 和 猪饲养员。
Interface Segregation Principle
Make fine grained interfaces that are client specific.
Classes should be as specialized as possible. You do not want any god classes that contain the whole application logic. The source code should be modular and every class should contain only the minimum necessary logic to achieve the desired behavior. The same goes for interfaces. Make small and specific interfaces so the client who implements them does not depend on methods it does not need. Instead of one class that can handle three special cases it is better to have three classes, one for each special case.
Example
In an adventure game, you have a class for your main character. The player can either be a warrior or an archer or a wizard. Instead of a class which can perform all the actions, like
strike,shootandheal, you would create three different classes, one for each character type. In the end, you would not only have aCharacterclass but also aWarrior, anArcherand aWizard, all inheriting fromCharacterand implementing their specific actions.
Dependency Inversion Principle
依赖倒置, 关注结构层 和 上层逻辑的定义, 让 底层依赖上层。
不是上层直接饮用底层,形成的依赖。
Dependency Inversion Principle
Depend on abstractions, not on concretions.
Classes should not depend on concrete details of other classes. Even classes from a high domain level should not handle the specific details of components from a lower level. Both low and high level classes should depend on the same abstractions. To create specific behavior you can use techniques like inheritance or interfaces.
Example
Imagine we have a class
Distributerwhich is able to share a blog post on different platforms. According to the Interface Segregation Principle the distributer uses a composition of several instances, like aTwitterShareActionand aFacebookShareAction. Now the goal of the Dependency Inversion Principle is to not depend on concrete methods of the share action classes, likesharePostOnTwitterandsharePostOnFacebook. Instead theDistributerclass would define an interface calledSharingwhich is implemented byTwitterShareActionandFacebookShareAction. It declares the abstract methodsharePost. TheDistributerclass doesn’t have to know the details of the concrete share actions. It just calls thesharePostmethod.
https://code-specialist.com/write-better-code/solid/
形象的例子。
The DIP violation here is that a switch is a concept that is logically in a layer above the light bulb, and the switch relies on it. This will lead to poor extensibility or even circular imports that prevent the program from being interpreted or compiled.
Dependency Inversion Violation
Instead of the light bulb telling the switch how the bulb should be handled, the switch should tell the light bulb how to implement it. The naive approach would be to define an interface that tells the light bulb how it should behave to be used with a switch.
Visualized as a class diagram, this source code would lead to the object-oriented design:
Dependency Inversion Solution
The dependency has been inverted. Instead of the switch relying on the light bulb, the light bulb now relies on an interface in a higher module. Also, both rely on abstractions, as required by the DIP. Last but not least, we also fulfilled the requirement “Abstractions should not depend upon details. Details should depend upon abstractions” – The details of how the device behaves rely on the abstraction (Device interface).

Dependency Inversion Violation
Dependency Inversion Solution
浙公网安备 33010602011771号