Object-oriented technology brings new development to software technology. People use object-oriented thought to analyze the system, model and design the system, and finally use object-oriented programming language to realize the system. But object-oriented design is not a very simple thing, especially to design a well-structured software system is not easy. In order to improve the reusability of the system, you need to do some “extras” design (and by extras I mean not useless, but outside of the business domain), defining the interfaces of the classes, planning the inheritance structure of the classes, and establishing relationships between classes. There is no doubt that good design makes it easier to reuse, migrate, and maintain a system, but how to achieve good design quickly is a design pattern to discuss the problem. Design pattern is a compulsory course for software architect, and the ideas contained in design pattern must be mastered by architect.

1 Overview of design patterns

In the 1970s, Christopher Alexander proposed the mode of urban architecture, and he believed that mode isto describe a constantly occurring problem and the solution of the problem. Subsequently, Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides wrote a famous reference book, Design Patterns: The Foundations of Reusable Object-oriented Software. Later generations also called the pattern described in this book the GoF (Gang of Four) design pattern because the book called these Four people a group of Four. In this book, the foursome defines design patterns as a description of classes and objects that communicate with each other to solve general design problems in a particular scenario. In layman’s terms, design patterns can be understood as a generic solution to a class of problems.

1.1 The concept of design patterns

First, design patterns address a class of problems, such as factory patterns addressing class creation and adapter patterns addressing class interface mismatches. If the design pattern that solved problem A were applied to problem B, the result would be the same. So before describing a design pattern, first describe what kind of problem the design pattern is trying to solve.

Second, design patterns are a general solution, not specific or unique. In GoF’s book, the design description mainly focuses on the description of the idea. Although C++ implementation method is also given, it can also be implemented in Java or even non-object-oriented languages. Specific application can be based on the actual situation of the corresponding changes, for example, there are many variations for the factory model.

It should be pointed out that although GoF first proposed the software design mode in his book, the design mode was not created by these four people. It was derived from successful designs in many projects, and these elegant design modes were abstracted, summarized and summarized.

The following two points need to be paid attention to when learning design patterns: (1) Learning these patterns is one aspect; on the other hand, it is more important to understand the ideas in the patterns. Design pattern itself is to improve the quality of software architecture, the purpose of learning design pattern is also to improve the level of architecture design. Although most of the design patterns are described in the object-oriented low-level design scheme, but it contains the idea of software design, which is consistent with the software architecture style. For example, MVC can be viewed as both a design pattern and an architectural style. Mastering this kind of design idea is very meaningful. (2) While design patterns can make design more sophisticated, abusing them can backfire. Using design patterns in software design can optimize design and improve architectural quality. However, first of all, design patterns have their application occasions, improper occasions to misuse design patterns harmful; Secondly, the design pattern mainly solves the structural relations between objects that communicate and depend on each other. Architects need to grasp the strength of using design pattern well. Excessive use of design pattern will not improve the reuse of software, but will make the architecture become chaotic and difficult to maintain.

1.2 Composition of design patterns

In general, a description of a design Pattern should include at least four aspects: Pattern name, Problem, Solution and Consequence. These four aspects are the four elements of a design pattern.

Every design pattern has its own name, which is the pattern name. Design pattern has its application occasions, that is, the design pattern is intended to solve the problem, beyond this problem should not be applied this pattern, so the problem is the second element of the design pattern; The purpose of design pattern is to solve problems, so in the description of design pattern, of course, there must be a description of the method to solve problems, which is another element of design pattern — solution; While architects know that applying design patterns improves architectural quality and software reuse, there is a more specific effect description for each design pattern, so the final element of a design pattern is effect.

These four elements are essential to describing design patterns.

1.3 GoF design pattern

GoF’s work was the first to summarize common patterns in design and establish software design patterns in academia. Therefore, the 23 patterns proposed by GoF are commonly referred to as GoF patterns, which are summarized as follows. (1) FactoryMethod mode. The FactoryMethod pattern provides a way to delay class creation by letting subclasses decide which instance of a class to create at run time. (2) AbstractFactory mode. AbstractFactory, also known as AbstractFactory pattern, mainly solves the problem of object creation in complex systems. The Abstract factory pattern provides a consistent object creation interface to create a series of objects with similar base classes or similar interfaces. Abstract factory pattern is a typical design pattern. (3) Builder mode. The Builder pattern is very similar to the AbstractFactory pattern, but the Builder pattern builds a complex object step by step and returns an instance of the object at the end. The Builder pattern can separate the creation and presentation of complex objects so that the same creation process can create different representations. Prototype mode. The Prototype pattern allows you to specify the type of object to be created based on the Prototype instance and to create new objects by deeply copying the Prototype. The Prototype pattern has the same effect as the AbstractFactory and Builder patterns, but you can use the Prototype pattern when the classes to be instantiated are specified at runtime and you want to avoid creating a hierarchy of factory classes that were once parallel to the product. Using the Prototype pattern allows you to add or subtract prototypes at run time, making it more flexible than the AbstractFactory and Builder patterns. (5) Singleton model. Singleton model is also a representative model. Using the Singleton pattern ensures that there is only one instance of a class, thus providing a single global access point. (6) Adapter mode. Adapter mode can solve the problem of system incompatibility. Adapter allows you to transform a class’s interface into the desired interface of the client, thereby increasing reusability. (7) Bridge mode. The Bridge pattern separates the abstract part of a class from the implementation part so that both the abstraction and implementation can change independently. (8) Composite mode. Composite mode provides a method to combine objects in a tree structure. Composite can be used to make a single object consistent with the combined objects to improve software reuse. (9) Decorator pattern The Decorator pattern can dynamically add more functionality to a method of an object. In many cases, the Decorator pattern allows you to maintain a clean class inheritance structure without having to extend new subclasses. (10) Facade pattern. The Facade pattern provides a consistent access interface for a set of classes. A Facade can encapsulate classes with different internal interfaces to provide uniform external access. The Facade pattern is developed into the Session Facade pattern in J2EE system development. (11) Flyweight mode. The Flyweight pattern can share a large number of fine-grained objects, saving the amount of space allocated to create objects, but increasing the overhead in time. (12) Proxy mode. As the name implies, the Proxy pattern provides an access Proxy for objects that can control client access. For example, you can control the access permission, access address, and access mode. You can even use Proxy to divide expensive access into parts to improve access efficiency. 13) Interpreter mode. Defines an interpreter to interpret sentences that follow a given language and grammar. (14) TemplateMethod model. Defines a template of operations, some of which are implemented in subclasses to suit different situations. (15) Chain of Responsibility mode. The Chain of Responsibility pattern organizes the objects that can respond to the request into a Chain and passes the request along the Chain of objects, thus ensuring that multiple objects have the opportunity to process the request and avoiding the coupling between the requester and the corresponding party. (16) Command mode. Encapsulate requests as objects to enhance the capabilities of requests, such as parameterization, queuing, logging, and so on. (17) Iterator mode. The Iterator pattern provides a way to sequentially access the elements of a collection of objects. Using Iterator avoids exposing the coupling of objects in the collection. (18) Mediator mode. Mediator mode can reduce the coupling between objects in the system. The Mediator pattern uses Mediator objects to encapsulate other objects so that the relationships between these encapsulated objects are loosely coupled. (19) Memento mode. The Memento pattern provides a way to capture the state of an object without breaking its encapsulation. You can also save the object’s state outside of the object and restore the object’s state if needed. (20) Observer mode The Observer pattern provides a way to broadcast the state of an object to a group of observers, allowing each Observer to be notified of updates to the object at any time. (21) State mode. The State pattern allows an object to change its behavior when its internal State changes. (22) Strategy model. Using the Strategy pattern allows changes in the algorithm in the object to be independent of the customer. (23) Visitor mode. Represents operations on elements in an object structure. Use the Visitor pattern to define new operations on those elements without changing the classes of the elements.

1.4 Other design modes

After GoF, people continue to explore design patterns and summarize more design patterns. In the J2EE application world, a number of design patterns have also been developed for applications developed using the J2EE framework. For example, the Intercepting Filter mode. In J2EE’s BPS (Basic Programming System) application framework, it is often necessary to do some pre-processing before actually responding to client requests. Such as customer authentication, customer Session validity verification, character set transcoding, customer request records, etc. It is certainly possible to preprocess these requests in each Servlet, but obviously the preprocessed code then “intrudes” into the real handler, making the code more difficult to maintain. The Intercepting Filter pattern provides a solution to this problem. It does this step by step by intercepting the customer request and sending it to the Filter chain until the request is forwarded to the Servlet that actually responds to the customer request.

1.5 Design patterns and Software Architecture

Software architecture describes the composition of software. For example, the classic “4+1” view describes software architecture in logical, development, process, physical, and scenario views. In these views, relationships between classes, relationships between processes, and the combination of software and hardware in a software system are described.

In general, software architecture tends to describe the composition of software as a whole and globally. Design patterns, on the other hand, focus more on the relationships between classes and objects. In a logical view, for example, you can use multiple design patterns to organize relationships between classes. Therefore, there are many people who believe that design patterns and software architecture are solutions to problems at different levels. Like design patterns, software architectures have fixed patterns, often referred to as architectural styles.

Common architectural styles include layered Architecture, client-server Architecture, message bus, service-oriented Architecture (SOA), and so on. Software architectural styles are in some sense consistent with design patterns. Design patterns and many of the ideas underlying software architecture are consistent.

In the process of pursuing good design, people summarize and sort out some common solutions to form a fixed style and pattern. For example, the message bus architectural style is similar to the Observer pattern. Therefore, mastering design patterns is of great help to software architecture design.

1.6 Classification of design patterns

It can be said that design patterns are problem-oriented, that is, each design pattern is designed to solve a particular type of problem. Therefore, design patterns can be divided into three types according to the problems to be solved by design patterns, namely, creation, structure and behavior.

In fact, object-oriented design, need to solve is: how to manage the object in the system, how to organize the system class and object, in the system class and object how to communicate with each other. These three design patterns solve these three problems respectively.

The creative design pattern addresses the problem of object creation. In the simplest case, you define the class in your program and create an object instance when you use it. However, in real development, object creation becomes much more complex, and the problem of object creation needs to be solved using the creative design pattern.

With the continuous expansion of the development system, the system functions become richer, the reuse between modules is more and more, and the structure of classes and objects in the system becomes more and more complex. Without good design, the relationships between these classes can get messy. Structural design patterns are designed to solve these problems. In addition to this classification method, GoF also proposes that design patterns can be classified according to whether they are mainly applied to classes or objects, which will not be discussed further. By integrating these two classification methods, GoF patterns can be classified, as shown in the following table.

Range of application Create a type structured Behavior type
Applied to the class Factory Method Adapter Interpreter, Template Method
Apply to objects Abstract Factory, Builder, Prototype, Singleton Adapter, Bridge, Composite, Decorator, Façade, Flyweight, Proxy Chain of Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy, Visitor

With the introduction of THE GoF design pattern, more examples of good design have been summarized and classified according to other methods. For example, in Core J2EE Patterns, the author divides the Design Patterns listed in the book into presentation, business, and composite Patterns. Based on this classification method, a design pattern map applied to the J2EE framework can be obtained, as shown in the following table.

The presentation layer The business layer Composite layer
Intercepting Filter, Front Controller, View Helper, Composite View, Service to Worker, Dispatcher View Business Delegate, Value Object, Session Façade, Composite Entity, Value Object Assembler, Value List Handler, Service Locator Data Access Object, Service Activator

2. Design mode and implementation

The realization of several common design patterns is discussed here.

2.1 Abstract Factory schema

(1) Mode name

Abstract Factory, also known as Abstract Factory pattern.

(2) Problems intended to be solved

Creating an object in a program may seem like a no-brainer, but it’s not. There are the following problems in large-scale system development: (1) Object New ClassName is the most common method to create objects, but this method causes hard coding of class names. It is necessary to dynamically load the same interface but implement different class instances according to different operating environments. Such creation method requires complex judgment and instantiation into different objects. (2) In order to adapt to different operating environments, we often use abstract classes to define interfaces and implement subclasses of this abstract class in different operating environments. Common creation methods inevitably result in strong binding of code to the runtime environment, and software products cannot be ported to other runtime environments.

The abstract factory pattern solves this problem by loading different instances of the same class with the same interface based on different configurations or contexts.

(3) Mode description

The structure of the Abstract Factory schema is shown in Figure 1.

Just like the name of the Abstract Factory, the Abstract Factory class will accept the “order” from the Client — the message sent by the Client, using a different “workshop” — a different Concrete Factory, According to the existing “Product model” — Abstract Product, a specific “Product” — Product is produced. Different workshops produce different products for use by customers, and the relationship between workshops and products is one-to-one. Because all products follow the Abstract Product model and have the same interface, these products can be delivered directly to customers. In the Abstract Factory pattern, an Abstract Factory can have multiple virtual methods similar to Create Product (), just as there are multiple Product lines in a Factory. Create Product 1() creates Product line 1, Create Product 2() creates Product line 2.

In Abstract Factory, the Create Product () method corresponds to the Abstract Product one by one, and the number of Concrete Factories is consistent with the number of actual products.

(4) Effect

The Abstract Product pattern can be used to create configurable and dynamic objects. Flexible application of Abstract Product pattern can improve the portability of software products, especially when software products run on multiple platforms or have different versions of functional configuration, Abstract factory pattern can reduce the pressure of migration and release, and improve the reuse of software.

(5) Relevant discussions

In practice, the Abstract Factory can be changed more flexibly. In fact, if you look closely at the Abstract Factory pattern, you can see that for clients, the primary concern is to have a consistent interface but different implementation of objects under different conditions, as long as you avoid hard-coding class names, other methods can be used to achieve this. So there are other ways to do it. In Java, for example, it can be implemented as an interface, as shown in Figure 2.

The class depicted in Figure 2 takes the Abstract Factory idea and implements the Factory pattern in a simple, interface-oriented manner. Product Factory can be regarded as either Abstract Factory or Concrete Factory.

One method is provided to get the product: getProduct (productName:String), which creates a specific product based on the name of the product and returns. All products implement the Product interface, which can be used in client programs.

As with the abstract factory pattern, the method of obtaining objects in the factory (getProduct()) is consistent with the actual number of Product lines, and if you want to add a new Product line — for example, defining a new Product interface Product X — you need to add the corresponding getProduct() method. Because this approach combines the Abstract Factory and Concrete Factory into a single Product Factory, no code changes are required to add a new Product that implements the Product interface.

In addition to this interface-oriented approach, the factory pattern can have many more variations. It has been said that learning design pattern is to learn the design idea, after learning the factory pattern, we should know: ① configurable object creation method can improve the system portability and reuse. ② Making full use of object-oriented polymorphism can avoid hard coding in the process of object creation.

2.2 the Singleton pattern

(1) Mode name

Singleton, also known as Singleton pattern or Singleton pattern.

(2) Problems intended to be solved

In software development, developers expect some service classes to have one and only one instance for other programs to use. For example, a short message service program or printer service program, or even control of the system configuration environment, may want to provide only one instance for other programs to avoid inconsistencies caused by concurrent access.

You can use a global variable for objects intended for use by the entire system, but a global variable only ensures that a unique instance is used for proper encoding. However, as the system continues to expand and the development team expands, there is still no guarantee that there is only one instance of this class in the system.

(3) Mode description

The Singleton pattern can solve the above problems, and its structure is shown in Figure 3.

Singleton is the simplest pattern from a structural point of view, but it has a wide range of uses. In Singleton, we prevent direct external initialization of the Singleton class by making its constructor protected (or private). Programs that need access to a Singleton must obtain one through the getInstance() method.

Creating a unique Instance just once in getInstance() guarantees a unique Instance in the system. There are two different Initialization strategies (Lazy Initialization and Early Initialization) for unique Instance in the Singleton. The code for both Initialization strategies will be provided in the implementation.

(4) Effect

Using the Singleton pattern ensures that there is one and only one instance in the system, which is important for many service classes or environment configuration classes.

(5) Relevant discussions

When using the Singleton pattern, note the following: (1) Singleton is only guaranteed to be a single instance within a single system. If you use distributed artifacts, such as EJBs running under multiple JVMS, the above implementation approach does not maintain a single instance across the entire system. (2) The Singleton mode is only applicable to the situation where there is at most one instance in the system, so abuse should be avoided. Many over-designed singletons are just as unnecessary and potentially inefficient as utility classes that use static methods. (3) As can be seen from the implementation of Singleton, Singleton does not support inheritance. For development languages that support Template technology, such as C++, Singleton templates can be defined to construct Singleton, further improving the reusability of the pattern. But in Java, C# and other languages, there are only other ways to implement.

However, Singleton classes are not the same as static classes, so in general, there are not and should not be many Singleton classes in the system, and it is possible to implement them one by one in languages that do not support templates. If you must implement batch Singleton classes in languages that do not support templates, you can refer to the methods in the literature.

2.3 the Decorator pattern

(1) Mode name

Decorator pattern, also known as Decorator pattern or painter pattern.

(2) Problems intended to be solved

During development, it is often found that the functionality pre-designed for a class is not powerful enough and needs to be enhanced or extended. The easiest way to solve this problem is to inherit a new class and extend the corresponding methods. But doing so creates a large number of subclasses, making the hierarchy of classes in the system complicated and confusing. The Decorator pattern solves the problem of extending functionality by wrapping a layer on top of the existing class.

(3) Mode description

The structure of the Decorator pattern is shown in Figure 4.

The Decorator Component is a Concrete Component Decorator class that inherits from the same abstract class Component and has the same interface. Concrete Decorator 1 and Concrete Decorator 2 are inherited as Concrete Decorator classes. This structure is clear at the class level and more flexible than static inheritance. The use sequence diagram in Figure 5 depicts the method of using the Decorator class.

According to the method in Figure 4, operations() with the same interface can have different behavior characteristics during the runtime according to the choice of customers to achieve dynamic function expansion.

(4) Effect

The Decorator pattern dynamically extends the functionality of a class without having to subclass it, and is more flexible than inherited methods. Because decorators provide dynamic extension methods, new Decorator classes can be generated on demand at any time, thereby avoiding some of the complexity of higher-level classes. However, heavy use of the Decorator pattern can result in a large number of small Decorator objects with similar interfaces, which can lead to a decrease in system maintainability.

(5) Relevant discussions

The Decorator pattern provides a way to dynamically extend functionality to a class and has a wide range of applications. For example, in the open source project DisplayTag (an open source project that provides JSP tag extensions that make it easy to draw beautiful tables on a web page, http:// displaytag.sourceforge.net/) provides Decorator extensions, Interfaces for secondary development also make extensive use of the Decorator pattern in THE JDK’s I/OAPI.

As with any pattern, misuse of decorators reduces the maintainability of your system. If you develop Decorator classes that are only used in a single place or are treated fairly simply, you need to consider whether the Decorator pattern is necessary.

2.4 the Facade pattern

(1) Mode name

The Facade pattern, also known as the Facade pattern, is also vividly translated as “Facade pattern”.

(2) Problems intended to be solved

Several other subsystems are often used in programs. When nothing is done, the interfaces of each subsystem need to be understood and used to make calls, leaving the system as chaotic as figure 6 shows.

These calls not only confuse the structure, but also greatly increase the coupling between the client and the subsystems, making it difficult to extend and maintain.

(3) Mode description

The structure of the Facade pattern is shown in Figure 7.

As shown in Figure 7, the Facade pattern solves the above problem by adding a layer in front of the existing system to encapsulate the interfaces of these subsystems and provide a consistent access interface externally.

(4) Effect

The Facade pattern hides the details of subsystems, reduces the complexity of clients using these subsystems, and reduces the degree of coupling between clients and subsystems. This changed from the need for all people to understand all the subsystem interfaces to the need for individual experts to abstract the subsystem interfaces.

The Facade pattern can be applied flexibly and without a specific implementation. The key to its application is to abstract a reasonable Facade interface.

(5) Relevant discussions

The Facade pattern well embodies the idea of encapsulation, which encapsulates the internal structure of a subsystem. For example, Data Access Objects (DAOs) are often encapsulated to separate Data Access from a concrete database. Clients can manipulate any supported database as long as they know the interface of the outermost database access component.

2.5 Mediator pattern

(1) Mode name

Mediator mode, also known as Mediator mode.

(2) Problems intended to be solved

There will be many objects in a complex system, and these objects will communicate with each other, resulting in the interdependence of objects. Modifying one object may affect several other objects, and the complex coupling of objects in the system reduces the maintainability of the system, making the system confusing and difficult to understand. Mediators decouple a system by encapsulating communication between a group of objects.

(3) Mode description

The structure of Mediator mode is shown in Figure 8.

In Mediator mode, a group of objects, a subclass of abstract Mediator, communicate through Concrete Mediators, which inherit from abstract Mediators. The communication interface defined in Mediator should be implemented to ensure the consistency of interfaces between Mediator classes and mutual communication classes.

The Mediator pattern looks like a messaging mechanism, but is quite different. Mediaor is not responsible for queuing, prioritizing, and so on messages, but it must respond to messages sent by a Colleague and send messages to a specific Colleague class. In other words, a Colleague is encapsulated in the Concrete Mediator class. Just like a Colleague, a human brain receives a message from the eyes saying “there is a pit ahead” and sends a message to the feet saying “stop going forward”.

(4) Effect

Mediator encapsulates a group of objects and reduces the coupling of a Colleague. A Colleague’s change does not affect other objects. Taking the front brain as an example, when walking, the brain receives a message from the eyes telling the foot to “stop”, while when driving, the brain receives this message and sends a message to the foot to “hit the brake”.

However, when there are more colleagues and the relationships among them are complex, Concrete Mediators will become very complicated and difficult to maintain.

(5) Relevant discussions

Mediator mode is widely used in GUI. When there are multiple objects that need to communicate with each other in a form or form or dialog box — for example, the drop-down list of people in the display department needs to change according to the different selection of the department drop-down list, using Mediator to encapsulate communication can reduce the coupling of these objects and improve the maintainability of the system.

Mediators often become very complicated. Not only does every object that needs to communicate need to know about the existence of mediators, but it also needs to know about the implementation of mediators. Therefore, the Mediator mode should be used only in a small area, otherwise the difficulty of maintaining the Mediator caused by too many colleagues would cancel out the advantages of the Mediator mode and make the system more difficult to maintain.

2.6 the Observer pattern

(1) Mode name

The Observer mode is also called the Observer mode.

(2) Problems intended to be solved

Due to the nature of object encapsulation, generally, the change of object state in the system is independent, that is, the change of object A state is not immediately reflected in object B. However, many objects in the system are interrelated. For example, in a stock market system, changes in stock status need to be reflected in multiple views at the same time — real-time quotes, technical analysis charts, etc. The simplest solution to this problem is to hardcode these associations. However, this will result in the tight coupling of objects in the system, and the system is difficult to maintain and reuse.

(3) Mode description

The structure of the Observer pattern is shown in Figure 9.

The abstract Subject class defines the topic class — the observed interface — whose subclass Concrete Subject notifies all observers of any state changes — Concrete Observer.

To maintain interface consistency, these observers inherit from the same abstract class Observer. The abstract classes keep a list of observers in the Subject, observers, and dynamically add or remove a particular observer through the attach and detach methods.

The observer added by subscription is unaware of any other observers and can only receive state changes of the observed subject object. In the notify method, the topic class sends state change messages to each observer, based on the list of observers that are currently enrolled in a subscription.

The setState() method in Concrete Subject indicates that the state of the object has changed, and this method calls notify method to update all observers, as shown in Figure 10.

(4) Effect

In the Observer pattern, abstract coupling between concrete objects and observers is implemented. Although the Subject knows which observers currently need to capture changes in their state, it does not know what they are doing; Each observer is only aware of the changes they have captured, but it is not clear how many observers are observing the state of the object, and there is no need to inform other observers.

Thus, dynamically adding and removing observers is very simple. The Observer pattern enables message broadcasting between objects, which is useful for many processes. However, the side effect of broadcasting is to increase the load on the system. Any message will be automatically sent to each observer, and each observer will respond to the message, which is not necessarily necessary.

(5) Relevant discussions

The Observer mode transforms the one-to-many object dependence into abstract coupling, improves the reuse value of the system, and is widely used. Smalltalk’s MVC architecture uses the Observer pattern to pass changes to the Model into the View.

However, improper use of the Observer can cause many problems. The update method described in Figure 10 ensures that all updates are notified to observers by the Subject automatically executing nofity() after setState() to send notifications to all observers.

But object state is not always isolated, and it is possible for a client to execute the setState1() method immediately after the setState2() method, or even to change the object’s state several times in a row. Thus, each change brings a Noifty () event, and these changes are amplified into each Observer object. Concurrent execution of the observer’s update() method is likely to cause errors, while exclusive access to the update() method is likely to cause blocking.

So notifications of object state changes are sometimes sent as shown in Figure 11.

This approach avoids the above problem by calling notify() after the client has executed a series of methods that change the state of the object. However, it does not guarantee that the changes in the state of the object will be notified to various observers, and it also makes the observers opaque to the client.

Therefore, it is important to avoid these problems when using the Observer pattern by precisely defining the dependencies of object state changes. It was also mentioned earlier that you can use the Observer to broadcast messages. Broadcasting is a double-edged sword. Although it can simplify the sending of one-to-many messages, it also brings a series of problems.

In the Observer mode, you should try to avoid broadcast enlargement. In the update() object, you should avoid updating the state of the Subject class, especially the state of the Subject class that you observe. Otherwise, an infinite loop of messages between objects can be created.

2.7 Intercepting Filter mode

(1) Mode name

The Intercepting Filter mode is also called the Filter mode.

(2) Problems intended to be solved

When MVC architecture is used for Web application development, it is usually necessary to preprocess the request from the customer, such as verifying the customer’s identity, verifying the source of the request, decoding the request, and then passing it to the controller. If all the preprocessing is done by the controller, it will increase the complexity of the controller, and it is difficult to maintain and expand.

(3) Mode description

The structure of the Intercepting Filter pattern is shown in Figure 12.

The FilterManager is responsible for scheduling the entire FilterChain. It intercepts the request before it reaches the Target and passes it to the FilterChain, which in turn is preprocessed by the filters in the FilterChain. The request is not fully preprocessed until it passes the last filter, and then the FilterManger forwards the request to the actual target. The timing relationship when using the InterceptingFilter mode is shown in Figure 13.

(4) Effect

Using the InterceptingFilter mode separates the pre-processing logic from the actual processing logic. The Target that does the actual processing only needs to care about the specific logic, while request-specific pre-processing takes place in the FilterManager. At the same time, the coupling of these two kinds of processing is removed, and it is easy to expand and modify the pretreatment process, and the system has better maintainability and expansibility.

(5) Relevant discussions

Although InterceptingFilter appears in relevant literature as a J2EE pattern, it has a wide range of applications. Not only J2EE development can use this mode to separate the preprocessing process, but also other Web applications such as.NET framework can use the InterceptingFilter.

A closer look at the InterceptingFilter pattern shows that it is similar to the Decorator pattern in that it adds a layer of operations that extend objects before they are actually processed. There’s just a big difference in implementation.

You can make the Intercepting Filter more versatile and easier to configure. If you need to use different Filter chains for different requests — for example, using different decoders depending on how the customer encodes them — you can use factory mode to dynamically create Filter objects for processing. There are many similar ways to use design patterns flexibly, and they can be applied to all kinds of patterns, requiring the architect to think deeply about the situation.

3. Summary of design patterns

The most important thing to learn about design patterns is to understand them, not to copy them. Each design pattern contains good design architecture ideas, such as hiding internal details, reducing coupling, etc., and the more complex the system needs these ideas to support.

If you look at human society, you see a lot of similarities with design patterns. Each human being is a well-encapsulated object, providing a medium of communication with the outside world through his senses and actions. There are only a few ways for human beings to receive messages, such as sight, hearing, smell and touch, but these sensory organs encapsulate the complex internal structure. Telescopes, telephones or other tools can be used to expand capabilities; For the complex human organization, there are indirect communication channels, intermediary provides a platform for communication; News organizations can keep people up to date on other people and things… Similar examples can be cited, such as broker and Proxy patterns are very similar, and most organizations look like Composite.

The ultimate purpose of a software system is to assist human activities. Only by abstracts the real world in a good way can a good design be obtained. There is no value in simply memorizing these patterns by rote, and a system that is easy to maintain and reuse can be obtained by associating with the actual situation. In practice, several patterns are often combined to solve complex problems. This requires the system architect to analyze the specific problems, eliminate the confusion and coupling in the system by comprehensive use of design patterns, and improve the system reuse.

It is important not to abuse design patterns, especially in simple systems. If the objects in the system are all created in factory mode, the tool classes in the system are all designed as Singleton, and the communication between the two objects requires a Mediator layer, it is not desirable. It can only increase the complexity of the system without any value, but is not conducive to the understanding and maintenance of the system. In addition to the initial design, refactoring is also a good time for the system architect to gradually apply design patterns as needed to improve the system and improve its maintainability and reusability.