Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the OOD principle of object-oriented design?

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

In this article, the editor introduces in detail "what are the OOD principles of object-oriented design". The content is detailed, the steps are clear, and the details are handled properly. I hope this article "what are the OOD principles of object-oriented design" can help you solve your doubts.

Single responsibility principle (SRP): a class should have only one reason to change, classes only need to know one thing, they should have a separate responsibility, and the point is that when a class needs to change, there should be only one reason.

Open-closed principle (OCP): software entities (classes, modules, functions, etc.) should be open for extension and closed for modification. This principle has a fairly detailed definition, but a simple meaning is that you should be able to change the surrounding environment of a module without changing the module itself.

Liskov substitution principle (LSP): subtypes (subtypes) must be replaceable for their base type (base types).

Principle of dependency inversion (DIP): A. High-level modules should not rely on lower-level modules, they should rely on abstraction.

B. abstraction should not depend on details, which should depend on abstractions.

A better description is: don't rely on specific classes that are easy to change. If you want to inherit a class, inherit from an abstract class. If you want to hold a reference to a class, reference it from an abstract class. If you want to call a function, call it from an abstract function.

Interface isolation principle (ISP): customers should not rely on methods that they do not use at all.

Summary:

The five simple principles are:

1. SRP-- there should be only one reason for a class to change.

2. OCP-- should be able to change the environment of a class without changing the class itself.

3. LSP-- avoids illegal or degenerate methods of a derived class, and users of a base class should not need to know about this derived class.

4. DIP-replace concrete classes with dependencies that are volatile with dependencies on interfaces and abstract classes.

5. ISP-- gives each user of an object an interface, which has only the methods that the user needs.

[@ more@] like the position of Newton's three laws in classical mechanics, the "open-close" principle (Open-Closed Principle) is the cornerstone of object-oriented reusable design (Object Oriented Design or OOD). Other design principles (Richter substitution principle, dependency inversion principle, synthesis / polymerization reuse principle, Dimitt rule, interface isolation principle) are the means and tools to realize the "open-closed" principle.

1. "Open-close" principle (Open-Closed Principle,OCP)

1.1 definition and advantages of the "open-closed" principle

1) definition: a software entity should be open to extensions and closed to modifications (Software entities should be open for extension,but closed for modification.). That is, when designing a module, the module should be extended without being modified.

2) the advantages of a system that satisfies the "open-closed" principle

A) by extending the existing software system, we can provide new behavior to meet the new requirements of the software, so that the changing software system has a certain degree of adaptability and flexibility.

B) the existing software modules, especially the most important abstract layer modules, can no longer be modified, which makes the changing software system have a certain degree of stability and continuity.

C) such a system satisfies both reusability and maintainability.

1.2 how to realize the "open-closed" principle

In object-oriented design, it is not allowed to change the abstraction layer of the system, while it is allowed to extend the implementation layer of the system. In other words, define an abstract design layer once and for all, allowing as much behavior as possible to be implemented at the implementation layer.

The key to solving the problem lies in abstraction, which is the first core essence of object-oriented design.

Abstracting a thing is essentially a summary of its essence. Abstraction allows us to grasp the most important things and think at a higher level. This reduces the complexity of thinking, and we don't have to think about so many things at the same time. In other words, we encapsulate the nature of things and can't see any details.

In object-oriented programming, through abstract classes and interfaces, the characteristics of concrete classes are defined as abstract layers, which are relatively stable and do not need to be changed, thus satisfying the requirement of "closing to modification", while concrete classes derived from abstract classes can change the behavior of the system to meet the requirement of "open to extension".

When you extend an entity, you don't have to change the source code or binary code of the software. The key is abstraction.

1.3 Encapsulation principles for variability

The "open-close" principle is the "encapsulation principle of variability" (Principle of Encapsulation of Variation, EVP). That is to find a variable of the system and encapsulate it. In other words, what might change in your design should be encapsulated as a layer of abstraction, not what would lead to a design change.

The "encapsulation principle of variability" means:

A) A variability should not be scattered in many corners of the code, but should be encapsulated in an object. Different representations of the same variability mean specific subclasses in the same inheritance hierarchy. Therefore, the emergence of inheritance relationships can be expected here. Inheritance is a way to encapsulate changes, not just to generate special objects from general objects.

B) one variability should not be mixed with another. The author believes that if the inheritance structure of the class diagram is more than two layers, it probably means that two different kinds of variability are mixed together.

Using the "variability encapsulation principle" to design can make the system comply with the "open-close" principle.

Even if the "open-close" principle cannot be achieved 100%, working in this direction can significantly improve the structure of a system.

Second, the principle of Liskov Substitution Principle substitution (LSP)

2.1 concept

Definition: if for every object O1 of type T1, there is an object of type T2 such that all program P defined by T1 does not change its behavior when all objects O1 are replaced with O2, then type T2 is a subtype of type T1.

That is, if a software entity uses a base class, it must be applicable to its subclasses. And it cannot detect the difference between a base class object and a subclass object. In other words, in the software, the base class is replaced with its subclasses, and the behavior of the program does not change.

The reverse substitution does not hold, and if a software entity uses a subclass, it does not necessarily apply to the base class.

Wherever a base class can appear, a subclass must appear.

The design based on contract abstracts the common part as the design of abstract base class.

2.2 the relationship between the Richter scale substitution principle and the "Open-closed" principle

The key step to realize the "open-closed" principle is abstraction. The inheritance relationship between base class and subclass is the embodiment of abstraction. Therefore, the Richter substitution principle is the specification of the concrete steps to realize abstraction.

Violating the Richter scale substitution principle means violating the "open-closed" principle, and vice versa.

Third, rely on the principle of inversion (dependence inversion principle, DIP)

3.1 concept

The principle of dependency reversal is to rely on abstraction, not on implementation. (Abstractions should not depend upon details. Details should depend upon abstractions.) program against the interface, not against the implementation. Program to an interface, not an implementation.

In other words, interfaces and abstract classes should be used for variable type declarations, parameter type declarations, method return type descriptions, and data type conversions. Instead of using concrete classes for variable type declarations, parameter type declarations, method return type descriptions, and data type conversions, etc. To ensure that this is done, a concrete class should implement only the methods declared in the interface and abstract class, rather than giving redundant methods.

The traditional design method of procedural system tends to make the high-level module rely on the low-level module and the abstract level depends on the concrete level. The principle of reversal is to reverse this false dependency.

The important principle of object-oriented design is to create abstraction, and to derive materialization from abstraction, which gives different implementations. Inheritance relationship is a kind of derivation from abstraction to concretization.

The abstraction layer should contain the business logic of the application system and macro strategic decisions that are important to the whole system, which is the embodiment of inevitability. The specific level contains some minor implementation-related algorithms and logic, as well as tactical decisions, with considerable accidental choices. The specific level of code is constantly changing, and errors cannot be avoided.

From the perspective of reuse, high-level modules should be reused, and it is the focus of reuse, because it contains the most important macro business logic of an application system, which is relatively stable. In the traditional process design, reuse focuses on the reuse of specific level modules.

The principle of relying on inversion is a "reversal" of the traditional process design method, and it is an effective specification of high-level module reuse and its maintainability.

Special case: the process of object creation violates the principle of "open-close" and the principle of dependency inversion, but the problem of dependency inversion in the process of object creation can be well solved through factory mode.

3.2 relationship

The relationship between the principle of "open-close" and the principle of dependence reversal is the relationship between goal and means. If the principle of opening and closing is the goal, relying on the principle of inversion is the means to achieve the principle of "opening and closing". If we want to achieve the best principle of "opening and closing", we should abide by the principle of relying on inversion as much as possible, and the principle of relying on inversion is the best norm for "abstraction".

The principle of Leigh substitution is the basis of the principle of relying on inversion, and the principle of relying on inversion is an important supplement to the principle of Richter scale substitution.

3.3 types of coupling (or dependency) relationships:

Zero coupling (Nil Coupling) relationship: there is no coupling relationship between the two classes

Concrete Concrete Coupling relationship: occurs between two concrete (instantiable) classes, resulting from a direct reference from one class to another concrete class.

Abstract coupling (Abstract Coupling) relationship: occurs between a concrete class and an abstract class (or interface), allowing maximum flexibility between two classes that must have a relationship.

3.3.1 how to grasp coupling

We should avoid implementing inheritance as much as possible for the following reasons:

1 loss of flexibility, the use of specific classes will bring trouble to the underlying modifications.

2 coupling problem, coupling refers to a measure that two entities depend on each other. Programmers make daily (consciously or unconsciously) decisions that affect coupling: class coupling, API coupling, application coupling, and so on. In an extended inheritance implementation system, the derived class is very closely coupled to the base class, and this tight connection may not be expected. Such as B extends A, when B does not use all the methods in A, the method called by B may produce an error!

We must objectively evaluate the degree of coupling, systems can not always be loosely coupled, then certainly nothing can be done.

3.3.2 what is the basis for us to determine the degree of coupling?

To put it simply, the degree of coupling is determined according to the stability of the demand. For requirements with high stability and requirements that are not easy to change, we can design all kinds of tightly coupled (although we discuss the coupling between classes, but in fact, the coupling between functional blocks, modules, and packages is also the same). Because this can improve efficiency, and we can also use some better technologies to improve efficiency or simplify code, such as internal class technology in c However, if the requirements are very likely to change, we need to fully consider the coupling between classes, we can think of a variety of ways to reduce the degree of coupling, but to sum up, it is nothing more than increasing the level of abstraction to isolate different classes, which can be abstract classes, concrete classes, interfaces, or a group of classes. We can summarize the idea of reducing coupling in one sentence: "programming for interfaces, not for implementation."

When we code, we will leave our fingerprints, such as the number of public, the format of the code, and so on. We can couple metrics to assess the risk of rebuilding code. Because rebuilding is actually a form of maintenance code, those troubles encountered in maintenance will also be encountered when rebuilding. We know that after rebuilding, most of the most common random bug is caused by improper coupling.

The greater the unstable factor is, the greater the coupling degree is.

Unstable factors of a certain class = number of dependent classes / number of dependent classes

Number of dependent classes = the total number of other classes that were compiled when this class was compiled

3.3.3 how to split a large system into small systems

One way to solve this problem is to assemble many classes into a higher-level unit to form a collection of classes with high cohesion and low coupling, which is a problem that we should focus on in the design process.

The goal of coupling is to maintain the unidirectionality of dependencies, and sometimes we need to use bad coupling. In this case, you should carefully record the reason to help future users of the code understand the real reason for using coupling.

3.4 how to achieve dependency reversal?

Coupling in an abstract manner is the key to relying on the inversion principle. Abstract coupling relations always involve concrete classes inheriting from abstract classes, and need to ensure that they can be changed to subclasses wherever they are referenced to the base class. therefore, the principle of Richter substitution is the basis of relying on the inversion principle.

Although coupling at the abstract level is flexible, it also brings additional complexity. If the possibility of a concrete class changing is very small, then the benefits of abstract coupling are very limited. It would be better to use concrete coupling at this time.

Hierarchical: all well-structured object-oriented architectures have a clear hierarchical definition, and each level provides a set of cohesive services to the outside through a well-defined and controlled interface.

Dependence on abstraction: it is recommended that you do not rely on concrete classes, that is, all dependencies in the program should be terminated on abstract classes or interfaces. Try to:

1. No variable should hold a pointer or reference to a specific class.

2. No class should be derived from a concrete class.

3. No method should override an implemented method in any of its base classes.

3.5 advantages and disadvantages of the principle of relying on inversion

Although the principle of relying on inversion is powerful, it is the most difficult to implement. Because of dependency inversion, object creation is likely to use object factories to avoid direct references to specific classes, and the use of this principle may also lead to a large number of classes, for engineers who are not familiar with object-oriented technology, maintaining such a system requires a good understanding of object-oriented design.

The principle of dependency reversal assumes that all specific classes will change, which is not always true. Some concrete classes may be quite stable and immutable, and applications using this concrete class instance can rely on this concrete type without having to create an abstract type for it.

IV. The principle of synthesis / polymerization reuse (Composite/Aggregate Reuse Principle or CARP)

4.1 concept

Definition: use some existing objects in a new object to make it part of the new object; the new object reuses these objects by delegating to them.

Synthesis / aggregation should be used first, synthesis / aggregation makes the system flexible, and then inheritance is considered to achieve the purpose of reuse. When using inheritance, we should strictly follow the principle of Richter scale substitution. The effective use of inheritance will help to understand the problem and reduce the complexity, while the abuse of inheritance will increase the difficulty and complexity of system construction and maintenance.

Composition and aggregation should be used if two classes are "Has-a" relationships, and inheritance can be used if they are "Is-a" relationships. "Is-A" is strictly taxonomically defined, meaning that one class is the "one" of the other. Unlike "Has-A", it means that a role has a certain responsibility.

4.2 what is synthesis? What is aggregation?

Composition and Aggregation are special types of Association.

Aggregation represents the relationship between the whole and the part, which means "ownership". Such as Mercedes-Benz S360, the relationship between Mercedes-Benz S360 engine and Mercedes-Benz S360 tires is aggregation. Without Mercedes-Benz S360, engines and tires will lose the meaning of existence. Aggregation should not occur frequently in the design, which will increase the coupling of the design.

Synthesis is a stronger "possession", and the part is the same as the life cycle of the whole. Synthetic new objects completely dominate their components, including their creation and annihilation. The component objects of one composite relationship cannot be shared with another composite relationship.

In other words, synthesis is Aggregation by Value of values, while aggregation is generally referred to as Aggregation by Reference of references.

If you understand the relationship between composition and aggregation, and then understand the principle of synthesis / aggregation, you should consider refactoring the code or redesigning the structure in order to avoid the occurrence of a class with more than three levels of inheritance in system design. Of course, the best way is to consider using the synthesis / aggregation principle.

4.3 advantages and disadvantages of synthesis / polymerization

Advantages:

1) the only way for new objects to access component objects is through the interface of component objects.

2) this kind of reuse is black box reuse, because the internal details of the component object are invisible to the new object.

3) this reuse supports packaging.

4) this kind of reuse requires less dependency.

5) each new class can focus on a task.

6) this kind of reuse can be carried out dynamically during run time, and the new object can dynamically reference objects of the same type as the component object.

7) as a means of reuse, it can be applied to almost any environment.

Disadvantage: there will be more objects to manage in the system.

4.4 advantages and disadvantages of reuse through inheritance

Advantages:

The new implementation is easier because most of the functionality of the superclass can be automatically entered into the subclass through inherited relationships.

It is easier to modify and extend inherited implementations.

Disadvantages:

Inheritance reuse destroys the wrapper because inheritance exposes the implementation details of the superclass to the subclass. Because the internal details of the superclass are often transparent to the subclass, this reuse is transparent reuse, also known as "white box" reuse.

If the superclass changes, so does the implementation of the subclass.

The implementation inherited from the superclass is static, cannot be changed in run time, and does not have enough flexibility.

Inheritance can only be used in a limited environment.

5. Dimitt's rule (Law of Demeter,LoD)

5.1 Overview

Definition: a software entity should interact with other entities as little as possible.

In this way, when one module is modified, it will affect other modules as little as possible. Expansion will be relatively easy.

This is a restriction on communication between software entities. It requires limiting the width and depth of communication between software entities.

5.2 other expressions of Demeter's rule:

1) only communicate with your direct friends.

2) Don't talk to "strangers".

3) each software unit has the least knowledge of other units, and is limited to those software units that are closely related to their own unit.

5.3 Demeter's rule in a narrow sense

If the two classes do not have to communicate directly with each other, then the two classes should not interact directly. If one of the classes needs to call a method of another class, the call can be forwarded through a third party.

The confirmation of moments.

"friend" condition:

1) current object itself (this)

2) objects passed into the current object method in the form of parameters

3) the object directly referenced by the instance variable of the current object

4) if the instance variable of the current object is an aggregation, then the elements in the aggregation are all friends.

5) the object created by the current object

Any object that satisfies one of the above conditions is a "friend" of the current object; otherwise, it is a "stranger".

Disadvantages: a large number of small methods will be created in the system, scattered in every corner of the system.

Complementary to the principle of dependency reversal

5.4 shortcomings of the narrow Dimitt rule:

Create a large number of small methods in the system, which only pass indirect calls and have nothing to do with the business logic of the system.

Following the Demeter rule between classes will simplify the local design of a system, because each part will not be directly related to remote objects. However, this will also reduce the communication efficiency between different modules of the system, and it will also make it difficult to coordinate between different modules of the system.

5.5 Demeter rule and design pattern

The facade (appearance) model and the mediator (intermediary) model are actually the specific applications of Dimitt's law.

5.6 Generalized Dimitt's rule

The main purpose of Dimitt's law is to control the overload of information. When applying Dimitt's rule to system design, pay attention to the following points:

1) in the division of classes, classes with weak coupling should be created.

2) in the structural design of the class, each class should minimize the access rights of the members.

3) in the design of a class, a class should be designed as an immutable class whenever possible.

4) in terms of references to other classes, an object's reference to its object should be minimized.

5.7 the embodiment of the generalized Dimitt rule in the design of classes

1) priority is given to setting a class to an immutable class

2) minimize the access rights of a class

3) use Serializable cautiously

4) minimize the access rights of members

5) replace C Struct

The Dimitt rule is also called the principle of least knowledge (Least Knowledge Principle or LKP), which means that an object should know as little as possible about other objects.

5.8 how to realize Demeter's rule

The main purpose of Dimitt's rule is to control the overload of information, so we should pay attention to the following points when applying it to system design.

1) in the division of classes, classes with weak coupling should be created. The weaker the coupling between classes, the more conducive to reuse.

2) in the structural design of the class, each class should minimize the access rights of the members. A class should not public its own properties, but should provide methods for values and assignments to allow the outside world to access its own properties indirectly.

3) in the design of a class, a class should be designed as an immutable class whenever possible.

4) in terms of references to other objects, a class's references to other objects should be minimized.

VI. Interface isolation principle (interface separate principle, ISP)

6.1 concept

Interface isolation principle: it is better to use multiple specialized interfaces than to use a single master interface. That is, the dependency of one class on another should be based on the smallest interface.

The "interface" here often has two different meanings: one refers to the collection of method characteristics of a type, which is only a logical abstraction, and the other refers to the specific definition of "interface" in a certain language. there are strict definitions and structures. Such as the Interface structure in the c # language. For these two different meanings, the expression and meaning of ISP are different. (a type mentioned above can be understood as a class, and we define a class, that is, a new type.)

When we understand the "interface" as a set of features of all the methods provided by a class, this is a logical concept. The division of interfaces directly leads to the division of types. Here, we can understand the interface as a role, an interface only represents a role, each role has its own specific interface, this principle can be called the "role isolation principle".

If "interface" is understood as a language-specific interface in a narrow sense, then ISP means that the same role provides different widths of interfaces for different clients, that is, customized services and personalized services. It only provides the behavior that the client needs, and the behavior that the client does not need is hidden.

Clients should be provided with a separate interface as small as possible, rather than a large overall interface.

This is also a restriction on communication between software entities. But it only limits the width of the communication, that is, the communication should be as narrow as possible.

Following the Demeter rule and the principle of interface isolation, when the function of a software system is extended, the pressure of modification will not be transferred to other objects.

6.2 how to implement the principle of interface isolation

Users should not be forced to rely on methods they do not use.

1. Use delegation to separate interfaces.

2. The interface is separated by multi-inheritance.

After reading this, the article "what are the OOD principles of object-oriented Design" has been introduced. If you want to master the knowledge of this article, you still need to practice and use it to understand it. If you want to know more about related articles, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report