Core principles of the object oriented design pattern

  • 2020-03-27 00:10:11
  • OfStack

1. Single responsibility

For a class, there should be only one reason for it to change.
If a class has too many responsibilities, it is coupling those responsibilities together, and changes in one responsibility may impair or inhibit the class's ability to perform other responsibilities. This coupling leads to fragile designs that can be unexpectedly damaged when changes occur.
A lot of what software design really does is discover responsibilities and separate those responsibilities from each other. If you have more than one motivation to change a class, that class has more than one responsibility.

2. Open and closed

Software entities (classes, modules, functions, etc.) should be extensible but not modifiable. That is, open to extension, closed to change.
In this design, the system can be relatively stable in the face of changing requirements, so that the system can continue to release new versions after the first version.
No matter how 'closed' a module is, there will be changes that cannot be closed. Since it is impossible to be completely closed, the designer must make a choice about what kind of change closure his module should have. He must first guess the most likely types of change and then construct abstractions to isolate those changes.
Take action when change occurs.

3. Dependency inversion

High-level modules should not rely on low-level modules. Both should rely on abstractions.
Abstractions should not depend on details, details should depend on abstractions.
Abstractions should not depend on details, details should depend on abstractions, program for interfaces, don't program for implementations.
Depend on the reverse in fact, that is a sign of object-oriented design, use what language to write programs is not important, if you consider when writing is how to abstract the programming details rather than programming, namely in the program ending all dependencies in the abstract class or interface, that is object-oriented design, whereas it is the procedural design.

4. Richter substitution

If a software entity is using a parent class, it must be applicable to its subclass, and there is no discernible difference between the parent and subclass objects. That is, in software, if you replace all the parent classes with its subclasses, the behavior of the program does not change.
Child types must be able to replace their parent types.
Only when the subclass can replace the parent class and the functionality of the software unit is not affected can the parent class be truly reused, and the subclass can add new behaviors on top of the parent class.

5. Composition/aggregation reuse

Try to use composition/aggregation instead of class inheritance.
Prioritizing composition/aggregation of objects will help you keep each class encapsulated and focused on a single task, so that the hierarchy of class and class inheritance remains small and unlikely to grow into an uncontrollable behemoth.

6. Demeter's rule

If two classes do not have to communicate directly with each other, then two classes should not interact directly. If one of the classes needs to call a method of the other class, a third party can forward the call.
In the structural design of classes, each class should reduce the access rights of its members as much as possible, that is, a class should wrap its private state and not expose fields or behaviors that need not be known to other classes.
The fundamental idea of Demeter's law is to emphasize loose coupling between classes.

The weaker the coupling between classes, the better it is for reuse, and a weakly coupled class can be modified without ripple effects on the related classes.

Supporting information:

Commonly used to create design patterns (other types of patterns are not mentioned, read their own books)

The creation pattern hides how instances of these classes are created and put together, and all the system knows about these objects is the interface defined by the abstract class. Thus, the creation pattern provides a lot of flexibility in what is created, who creates it = how it is created, and when.

1. Factory Method

Define an interface for creating objects, let subclasses decide which classes to instantiate, and factory mode delays instantiation of a class to its subclasses.
Creation patterns abstract the process of instantiation, and they help a system to be independent of how those objects are created, composed, and represented. The creation pattern encapsulates information about which specific classes the system USES. Allows customers to configure a system with very different structure and function 'product' objects. Configuration can be static, specified at compile time, or dynamic, specified at run time.
Usually design should start with a factory approach, and as the designer sees the need for more flexibility, the design evolves to other creative patterns. Understanding multiple creative patterns can give designers more options when weighing design criteria.

2. Abstract Factory

Provides an interface to create a series of or related dependent objects without specifying their specific class.

3. Builder mode

Separating the construction of a complex object from its representation allows the same build process to create different representations.
Cohesion and coupling cohesion describe how closely the internal components of a routine relate to each other. Coupling, on the other hand, describes how closely one routine is related to other routines. The goal of software development should be to create routines that are internally complete, that is, highly cohesive, and whose connections to other routines are small, direct, visible, and flexible, and thus loosely coupled.
Separating the construction of a complex object from its representation makes it easy to change the internal representation of a product and to separate the construction code from the presentation code. This way, for the customer, it doesn't have to care about the product creation process, but just tell me what I need, and I can use the same build process to create different products for the customer.

4. Prototype

Specify the types of objects to create with instances of the stereotypes, and create new objects by copying those stereotypes.
It is often more convenient to prototype the number of dependencies and clone them than to manually instantiate the class each time in the appropriate state.

5. Singleton pattern

Ensures that a class has only one instance and provides a global access point to it.
For some classes, an instance is important. A global variable can make an object accessible, but it cannot prevent clients from instantiating multiple objects. The advantage of a singleton is that it is the responsibility of the class itself to hold its unique instance. This class guarantees that no other instance can be created, and the singleton also provides a way to access that instance. This allows strict control over how and when clients access a unique instance.

Related articles: