3. Design pattern

3. Design pattern

Most of the design patterns are to solve the problem of code scalability
. In the early stage of development, unless it is particularly necessary, we must not over-design and apply complex design patterns. Instead, when there is a problem with the code, we then refactor the problem, apply principles and patterns. This can effectively avoid over-designing in the early stage

What design patterns do is decoupling.
The creation mode is to decouple the creation and use codes,
the structural mode is to decouple different functional codes, and
the behavioral mode is to decouple different behavioral codes

1. Create

Commonly used are: singleton mode, factory mode (factory method and abstract factory), builder mode.
Not commonly used are: Prototype mode

The creational pattern mainly solves the problem of object creation, encapsulates the complex creation process, and decouples the creation code and usage code of the object.

  • The singleton pattern is used to create globally unique objects.
    Classic implementation:

    Hungry, lazy, double checking, static inner classes, enums

    Alternative singleton solution:

    Global uniqueness is guaranteed through factory patterns and IOC containers.

  • The factory pattern is used to create different but related types of objects (a group of subclasses that inherit the same parent class or interface), and the given parameters determine which type of object to create.
    If the logic of creating an object is not complicated, then it is enough to create the object directly through new , without using the factory pattern. When the creation logic is complex and is a "big project", consider using the factory pattern to encapsulate the object creation process and separate the creation and use of the object.

    • The factory mode is a very classic application scenario: a dependency injection framework (such as Spring IOC), which is used to create, assemble, and manage objects in a centralized manner, decoupled from specific business codes, and let programmers focus on the development of business codes.


      The reference standard for judging whether to use the factory model:

    1. Encapsulation changes: The creation logic may change. After being encapsulated into a factory class, the change of the creation logic is transparent to the caller.
    2. Code reuse: Create code that can be reused after being separated into an independent factory class.
    3. Isolate complexity: Encapsulate complex creation logic, and the caller does not need to understand how to create objects.
    4. Control complexity: Extract the creation code to make the original function or class have a single responsibility and the code is more concise.

  • The builder mode is used to create complex objects, which can be "customized" to create different objects by setting different optional parameters.

    • Application scenario:

    1. The required attributes of the class are placed in the constructor, and they are set when the object is forced to be created. If there are many required attributes, if these required attributes are set in the constructor, then the constructor will have a long parameter list. If we set the required attributes through the set() method, then the logic to verify whether these required attributes have been filled has nowhere to be placed.
    2. There are certain dependencies or constraints between the attributes of the class. Using the constructor with the design idea of ​​the set() method, there is nowhere to put the verification logic of these dependencies or constraints.
    3. Create an immutable object. After the object is created, the internal attribute values ​​cannot be modified. To achieve this function, the set() method cannot be exposed in the class. The way that the constructor cooperates with the set() method to set the property value is not applicable.

  • Prototype mode creates objects with relatively high creation costs by duplicating existing objects to save creation time.

2. Structural type

Commonly used are: proxy mode, bridge mode, decorator mode, adapter mode.
Less commonly used ones are: facade mode, combination mode, flyweight mode.

Structural design patterns mainly solve the problem of "combination or assembly of classes or objects"

  • Proxy mode: The proxy mode defines a proxy class for the original class without changing the interface of the original class. The main purpose is to control access, not to enhance functions. This is the biggest difference from the decorator mode.

    • Application scenario:

      Non-functional requirements, such as: monitoring, statistics, authentication, current limiting, transactions, idempotence, logs, RPC, caching and other application scenarios.

  • Bridge mode: The purpose of the bridge mode is to separate the interface part from the implementation part, so that they can be changed relatively easily and relatively independently.

    Interface does not refer to "abstract class" or "interface", but a set of abstracted "class library", which only contains skeleton code, and the real business logic needs to be delegated to the "implementation" in the definition to complete .
    Implementation is not an "interface implementation class", but a set of independent "class libraries".
    "Abstract" and "implementation" are developed independently and assembled together through the composition relationship between objects.

  • Decorator mode: The decorator mode enhances the function of the original class without changing the interface of the original class, and supports the nested use of multiple decorators.

    It mainly solves the problem that the inheritance relationship is too complicated, replaces the inheritance by combination, and adds enhanced functions to the original class.
    Multiple decorators can be nested on primitive classes. The decorator class needs to inherit the same abstract class or interface as the original class.

  • Adapter pattern: The adapter pattern is an afterthought remedial strategy. The adapter provides a different interface from the original class, while the proxy mode and decorator mode provide the same interface as the original class.

  • Facade mode: By encapsulating fine-grained interfaces and providing high-level interfaces that combine each fine-grained interface, it improves the usability of the interface, or solves problems such as performance and distributed transactions.

  • Combination mode: used to process tree-structured data. The data must be able to be represented in a tree structure, and single objects and combined objects are regarded as nodes in the tree to unify the processing logic, recursively process each subtree, and simplify code implementation in turn.

  • Flyweight mode: The premise is that the flyweight object is an immutable object.

3. Behavioral

Commonly used are: Observer mode , template mode , strategy mode , chain of responsibility mode , iterator mode
, state mode
Not commonly used are: visitor mode, memo mode, command mode, interpreter mode, intermediary mode

The behavioral design pattern mainly solves the problem of "interaction between classes or objects"

  • Observer pattern: Decouple the observer and the observed code.

    From decoupling at the code level to system decoupling at the architecture level, or some product design ideas, there is a shadow of this model. For example, email subscriptions and RSS Feeds are essentially observer models.

  • Template mode: Define an algorithm skeleton in a method and defer certain steps to subclasses.

    Two major functions: reuse and expansion. Among them, reuse means that all subclasses can reuse the code of the template method provided in the parent class. Extension means that the framework provides functional extension points through the template mode, allowing framework users to customize the functions of the framework based on the extension points without modifying the source code of the framework.

    • Callbacks serve the same purpose as template patterns: code reuse and extension. (JdbcTemplate uses callbacks)

      The callback is implemented based on the composition relationship, and the template mode is implemented based on the inheritance relationship. Callbacks are more flexible than template patterns.

  • Strategy pattern: the definition, creation, and use of decoupling strategies.
    Application scenario:

    1. Avoid lengthy if-else or switch branch judgments.
    2. Provide extension points of the framework.
    3. For complex code, the strategy mode can also satisfy the open-close principle. When adding a new strategy, it minimizes and centralizes code changes and reduces the risk of introducing bugs.

  • Chain of Responsibility Pattern: Multiple processors process the same request sequentially. Each processor in the chain assumes its own processing responsibilities
    Application scenarios:

    Implement filter and interceptor functions, allowing framework users to add new filtering and interception functions without modifying the source code of the framework.

  • Iterator mode: used to traverse collection objects. The main function is to decouple container code and traversal code .

  • State mode: It is commonly used in system development such as games and workflow engines.

    It consists of 3 parts: state, event, and action. Among them, an event is also called a transition condition. Events trigger the transition of states and the execution of actions. However, the action is not necessary, and it is possible to just transfer the state without performing any action.

  • Visitor mode: Allows one or more operations to be applied to a set of objects. The design intent is to decouple the operation and the object itself, keep the class with a single responsibility, satisfy the principle of opening and closing, and deal with the complexity of the code.

    For the visitor mode, the main difficulty of learning lies in the code implementation. The main reason why the code implementation is more complicated is that function overloading is statically bound in most object-oriented programming languages. That is to say, which overloaded function of the class to call is determined by the declared type of the parameter during compilation, not by the actual type of the parameter at runtime. Because the code implementation is difficult to understand, applying this pattern in the project will lead to poor readability of the code.

  • Memento mode: The snapshot mode captures the internal state of an object without violating the principle of encapsulation , and saves this state outside the object , so that the object can be restored to its previous state later .
    Application scenario:

    It is mainly used to prevent loss, undo, restore, etc.

  • Command mode: The core implementation method is to encapsulate functions into objects.
    Application scenario:

    Used to control the execution of commands, such as asynchronous, delay, queue execution commands, undo redo commands, store commands, log commands, etc.

  • Interpreter mode: The core idea is to divide the work of grammar analysis into various sub-categories, so as to avoid large and comprehensive analysis of classes. The general approach is to split the grammatical rules into some small independent units, then parse each unit, and finally merge them into the parsing of the whole grammatical rules.

  • Intermediary mode: The design idea is very similar to the middle layer. By introducing the intermediary layer, the interaction relationship between a group of objects is converted from many-to-many (network relationship) to one-to-many (star relationship). In this way, the interaction between objects is minimized, the complexity of the code is reduced, and the readability and maintainability of the code are improved.

Guess you like

Origin blog.csdn.net/weixin_46488959/article/details/126918523