Structural Patterns of Design Patterns

Article directory

Creation pattern (5)

factory method pattern, abstract factory pattern, singleton pattern, builder pattern, prototype pattern.

(Memory: the method of abstract imagination , building an original single factory )

Structural mode (7)
[adapter mode] , decorator mode, proxy mode, appearance mode, bridge mode, combination mode, flyweight mode

Behavior pattern (11)
strategy pattern, template method pattern, [observer pattern] , iterative sub pattern, responsibility chain pattern, command pattern, memorandum pattern, state pattern, visitor pattern, mediator pattern, interpreter pattern.

All [design patterns] are designed for programs to better satisfy these six principles. There are a total of 23 design patterns. Today we will first learn about constructive patterns. There are five in total, namely:

  • adapter mode
  • Decorator pattern
  • proxy mode
  • Appearance Mode
  • bridge mode
  • Combination mode
  • flyweight pattern

1. Adapter mode

Adapter definition:

Structure of the Adapter Pattern

  • Target interface: the interface expected by the current system business, which can be an abstract class or interface.
  • Adaptee class: It is the component interface in the existing component library that is accessed and adapted.
  • Adapter class: It is a converter that converts the adapter interface into the target interface by inheriting or referencing the adapter’s object, allowing customers to access the adapter in the format of the target interface

Structure diagram of the class adapter pattern

Structure diagram of the object adapter pattern

Structure diagram of the class adapter pattern

target interface

Adapter interface/class
class adapter

client code

Code Base Patterns for Object Adapters

The main change is to use the constructor to pass parameters instead of inheritance (solving the shortcomings of java single inheritance), other codes remain unchanged
client test code

Most of the codes on the Internet stop there, but the more I read, the more I feel that something is wrong. For example, one interface is MP3 – method play(), and the other is MP4 – method play. Finally, I adapted MP4, but my original Where does the mp3 function go? Is there any way to keep my previous mp3 function and adapt it to mp4 function?

The following scenarios will help you solve this problem.

Case Showcase of Practical Application Scenarios

Case scenario: We have a MediaPlayer interface and an entity class AudioPlayer that implements the MediaPlayer interface. By default, AudioPlayer can play audio files in mp3 format.

We have another interface AdvancedMediaPlayer and an entity class that implements the AdvancedMediaPlayer interface. This class can play files in vlc and mp4 format.

MP3 player interface

  • The audioType is added here, which can be used to determine who’s additional functions are used according to the type passed in the sequence.

AdvancedMediaPlayer

  • The interface of the advanced player defines the functions that can play vlc and mp4 respectively

Implementation class of vlc player
Implementation class for MP4 player

Create an adapter class that implements the MediaPlayer interface.

  • Note here that when re-constructing the method, the object that uses the advanced player is mainly judged according to the type, and then play is used to call additional functions (what about my previous mp3 function?)

Create an entity class that implements the MediaPlayer interface.

  • The starting point here is the MP3 playback implementation class. It can be seen that when he perfects his MP3 playback and deploys his own functions at the same time, he uses the adapter to add additional functions.

  • AudioPlayer is used here to play different types of audio formats.

Advantages and Disadvantages of the Adapter Pattern

advantage

  • The client can transparently call the target interface through the adapter.
  • Existing classes are reused, and the programmer does not need to modify the original code to reuse the existing adapter classes.
  • Decoupling the target class and the adapter class solves the problem of inconsistent interfaces between the target class and the adapter class.
  • It conforms to the open-closed principle in many business scenarios.

shortcoming

  • The adapter writing process needs to be comprehensively considered in combination with business scenarios, which may increase the complexity of the system.
  • Increase the difficulty of code reading, reduce code readability, and excessive use of adapters will make system code messy

Second, the [decorator] mode

The decorator pattern has to be defined

Common decorator usage scenarios

Base code interface for the decorator pattern

abstract component role
specific component roles
abstract decorative character
specific decorative roles

  • The last highlight of the decorator is that the super method is called, which is very similar to aop here.

test class

Actual combat, project status before reconstruction
However, with the continuous development of the business, specialized operation personnel, marketing personnel, and data personnel began to appear in the team. Each personnel has different needs for the use of ERP, some need to create activities, and some just view data. At the same time, in order to ensure the security of data, every user will not have the highest authority.
Then the SSO used in the past is a componentized general service, and the required user access authentication function cannot be added on the surface. At this time, we can use the decorator pattern to expand the original single sign-on service. But at the same time, it also ensures that the original functions are not damaged and can continue to be used.

1 Mock Spring’s HandlerInterceptor

This is our custom, just to simulate the interception of the interceptor.

2. Simulate the interception of single sign-on

  • The simulation implementation here is very simple, just intercept the string. In actual use, you need to obtain the cookie information from the HttpServletRequest request object, and parse the ticket value for verification.
  • It is also very simple in the return, as long as the success is obtained, it is considered to be allowed to log in.

  • Simulate the scenario of employee login

  • write test class

Summary: The LoginSsoDecorator above extends those access rights the user has for the previous interceptor returning sucess.

Before refactoring, there are the following points, which need to be specially explained.
There are four more important points abstracted in the decorator pattern;

  1. Abstract Component Role (Component) – defines an abstract interface
  2. Concrete Component Role (ConcreteComponent) – implements an abstract interface, which can be a set of
  3. Decorator – Define an abstract class and inherit the methods in the interface to ensure consistency
  4. ConcreteDecorator – Extends the specific implementation logic of the decoration

abstract decorative class

  • There are two points of interest in decorating classes: 1) inheriting the handle interface, 2) providing a constructor, and 3) overriding the method preHandle.
  • The above three points are the core processing part of the decorator pattern, which can eliminate the way of subclass inheritance to realize logical function extension

Decorative role logic implementation

  • In the implementation of the specific decoration class, the decoration class SsoDecorator is inherited, then the method can now be extended;
  • As can be seen in the implementation of preHandle, this only concerns the functions of the extension part, and will not affect the core services of the original class, nor will it increase the redundant subclasses caused by the use of inheritance. overall flexibility.

test class

Summary: The biggest difference can be found from the graph below
There is no pre-refactoring on the left: SsoInterceptor has implemented the relevant interception judgment code before, and as a result, it has continued to be rewritten in OldLoginSsoDecorator.

The refactored one on the right: the duplicated code, I can just superimpose it in one go.

The big point here is that

From this, we also know the related logic of intercepting strings, which is judged to be implemented in SsoInterceptor. Here he did not integrate SsoInterceptor. Why can the previous implementation of SsoInterceptor be called directly by super?

The point is: the following construction parameters, so that you can flexibly supervise the implementation of different implementation classes according to the construction method.
So as to achieve the effect of the final test class.

@Test
    public void test_LoginSsoDecorator() {
        LoginSsoDecorator ssoDecorator = new LoginSsoDecorator();
        String request = "1successhuahua";
        boolean success = ssoDecorator.preHandle(request, "ewcdqwt40liuiu",
                "t");
        System.out.println( "Login check: " + request + (success ? "Let" : " Block
                Cut" ));
    };
}

Advantages and disadvantages of the decorator pattern

advantage

  • Decorator is a powerful complement to inheritance, which is more flexible than inheritance. Without changing the original object, it can dynamically extend functions to an object, plug and play.
  • By using non-decorated classes and the arrangement and combination of these decorative classes, different effects can be achieved. The decorator pattern fully adheres to the open and closed principle.

shortcoming

  • The decorator pattern will add many subclasses, and overuse will increase the complexity of the program.

3. Agency Mode

The main structure of the agent’s schema

  • Abstract subject (Subject) class: declares the real subject and the business method implemented by the proxy object through an interface or abstract class.
  • Real Subject (Real Subject) class: implements the specific business in the abstract subject, is the real object represented by the proxy object, and is the final object to be referenced.
  • Proxy (Proxy) class: provides the same interface as the real subject, which contains a reference to the real subject, which can access, control or extend the functions of the real subject.

Code Base Patterns for Proxy Patterns

In the starting project, we manage the proxy, and the jdk proxy and cglib proxy are the most used. They are all one of the implementation methods of the proxy mode, and I will describe their use and differences below.

JDK dynamic proxy

  • We define an interface, define its access prefix and suffix

An implementation class that implements this interface

Proxy interface and implementation class

  • At this time, if he does not implement this interface, if the jdk proxy reports an error, cglib will be fine

proxy class

test class

Cglib dynamic proxy

The interface and implementation class of AOP remain unchanged
. There is no implementation interface here.

proxy class

test class

Difference between CGLIB and JDK dynamic proxy

  • Jdk dynamic proxy: use interceptor (must implement InvocationHandler) plus reflection mechanism to generate an anonymous class of proxy interface, call InvokeHandler to process before calling specific method

  • Cglib dynamic proxy: Using the ASM framework, load the class file generated by the proxy object class, and generate subclasses by modifying its bytecode to process

  • JDK dynamic proxy can only generate proxy for the class that implements the interface, but not for the class Cglib is for the class.

Cglib is faster than JDK

The bottom layer of cglib is the ASM bytecode generation framework, but the bytecode technology generates proxy classes, which is more efficient than using java reflection
before JDL1.6. After jdk6, the JDK dynamic proxy has been gradually optimized, and the efficiency is low when the number of calls is relatively small. The proxy efficiency is higher than that of cglib
. Only when a large number of calls are made, the efficiency of cglib is high, but the efficiency of JDK is higher than that of cglib in 1.8.

How does Spring choose whether to use JDK or cglib

  • The target object generates an interface that uses JDK dynamic proxy by default
  • If the target object does not implement the interface, the cglib library must be used,
  • You can set it yourself, even if the object does not generate an interface, you can force the use of cglib

4. Appearance Mode

What is Appearance Mode

Structure of Appearance Mode

  • Facade role: Provides a common interface for multiple subsystems to the outside world.
  • Sub System role: implements part of the functionality of the system, and clients can access it through the appearance role.
  • Client role: access the functions of various subsystems through a facade role

Java Basic Structure of Facade Mode

Subsystem role

appearance role

test class

  • From the above basic structure, we can see that the appearance mode is roughly similar to the way we develop commonly used encapsulation methods.

case simulation
In addition, this is a type of common requirement with general logic, which is very suitable for developing into components to manage services and allow R&D personnel to focus more on
business function development.

scene description

general solution

  • The code in the whitelist occupies a large part, but it is not the logic in the business, but because of the pre-opening test and verification that we need to do in the process of going online.
  • If you often develop such requirements in this way, you can optimize your processing method according to this design pattern to make subsequent expansion and removal easier

after refactoring

Configure service class

Configuration class annotation definition

  • It is used to define the configuration information for adding itstack.door in application.yml later.

Get custom configuration class information

  • The above code is the configuration acquisition operation, mainly the definition of annotations
    ; @Configuration , @ConditionalOnClass , @EnableConfigurationProperties , this
    part is mainly used in combination with SpringBoot

Aspect Annotation Definition

  • The appearance mode page annotation is defined, and this annotation is added to the method that needs to expand the whitelist.
  • Two input parameters are provided here, key: get a field such as user ID, returnJson: determine the
    specific content returned after whitelist interception

Whitelist Aspect Logic

  • This includes a lot of content, and the core logic is mainly: Object doRouter(ProceedingJoinPoint jp), then
    we will introduce
    @Pointcut(“@annotation(org.itstack.demo.design.door.annotation.DoDoor)”)
    To define an aspect, the annotation path is used here, that is, all methods that add this annotation will be managed by the aspect.
    getFiledValue
    obtains the specified key, that is, obtains an attribute in the input parameter. This is mainly to obtain the user ID and perform interception verification through the ID.
    returnObject
    returns the intercepted conversion object, that is to say, when non-whitelisted users access, some prompt information is returned.
    The core logic of the doRouter
    section, this part is mainly to determine whether the currently accessed user ID is a whitelist user, if so, let
    jp.proceed(); , otherwise return a custom interception prompt message

Test verification

We will perform the test here in the project: itstack-demo-design-10-00, and verify by importing the jar package and configuring
annotations

In this test, we will operate in the project: itstack-demo-design-10-00, and verify by importing jar packages and configuring annotations
3.1
Introducing middleware POM configuration

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>itstack-demo-design-10-02</artifactId>
</dependency>

Package middleware projects and provide jar package services to the outside world

3.2 Configure application.yml

This is mainly to add the switch of the whitelist and the user ID of the whitelist, separated by commas.

Add custom annotations in Controller

The core content here is the addition of custom annotations @DoDoor, which is our middleware implementation of appearance mode.
key: The attribute field that needs to get the value from the input parameter, if it is an object, get the value from the object, if it is a single value, use it directly.
returnJson: The return value during preset interception is the Json of the returned object.

Start SpringBoot

  • http://localhost:8080/api/queryUserInfo?userId=1001

5. [Flyweight Mode]

Definition of Flyweight Pattern

The structure of the flyweight pattern

  • Abstract Flyweight role (Flyweight): It is the base class of all concrete Flyweight classes. It is the public interface that specific Flyweight specifications need to implement. Non-Flyweight external states are passed in through methods in the form of parameters.
  • Concrete Flyweight role: Implement the interface specified in the abstract Flyweight role.
  • Unsharable Flyweight role: It is an external state that cannot be shared. It is injected into the related methods of specific Flyweight in the form of parameters.
  • Flyweight Factory role: Responsible for creating and managing Flyweight roles. When a client object requests a flyweight object, the flyweight factory checks whether there is a flyweight object that meets the requirements in the system, and if it exists, it is provided to the client; if it does not exist, a new flyweight object is created.

Basic code structure of flyweight pattern

non-flyweight roles

abstract flyweight role
Specific flyweight roles
Flyweight Factory Role
test class

Case scenario simulation

The shared bicycles that can be seen everywhere in the city are a typical case of the “Flywon model”, in which the brand of the bicycle is fixed and the person who uses it is uncertain. Let’s do it with code.

User class

Shared transport abstract class

Vehicle, bicycle implementation class

bicycle factory

client test class

Advantages and disadvantages of flyweight model

advantage:

  • Only one copy of the same object is saved, which reduces the number of objects in the system, thereby reducing the pressure on memory caused by fine-grained objects in the system.

shortcoming:

  • In order to make objects sharable, some state that cannot be shared needs to be externalized, which will increase the complexity of the program.
  • Reading the external state of the flyweight pattern makes the runtime slightly longer.

6. [Bridge] mode

What is Bridge Mode

In real life, some classes have two or more dimensions of variation, such as graphics can be divided by shape, but also by color. How to design a software like Photoshop that can draw graphics of different shapes and colors? If the inheritance method is used, there are m×n kinds of graphs with m shapes and n colors, which not only correspond to many subclasses, but also difficult to expand.

Of course, there are many more such examples, such as text in different colors and fonts, cars of different brands and power, men and women of different genders and occupations, media players that support different platforms and different file formats, etc. If the bridge mode can solve these problems very well.

Structure of Bridge Mode

  • Bridge mode includes the following main roles.
  • Abstraction role: Defines an abstract class and contains a reference to the realized object.
  • Extended Abstraction (Refined Abstraction) role: It is a subclass of the abstracted role, implements the business methods in the parent class, and calls the business methods in the implemented role through the composition relationship.
  • Implementor role: Define the interface of the implementor role, which is called by the extended abstract role.
  • Concrete Implementor role: Gives the concrete implementation of the interface of the implemented role.

Basic code implementation of bridge mode

realization role

abstract role

test class

Scenario Simulation
In the front, we understand that the bridge mode mainly solves the problem of n situations when there are m conditions. At this point, let’s take a scenario: design a program with a power on and off for different brands and types of notebooks. For example, notebooks, there are Huawei notebooks, Xiaomi notebooks. At the same time, some of these notebooks are divided into business notebooks and gaming notebooks.

Computer brand interface => corresponding behavior implementation class interface:
Notebooks of different brands => concrete implementation classes for behavior implementation:

huawei notebook

xiaomi notebook

Different kinds of notebooks => subclasses of corresponding abstract classes:

Through the class, the two relationships of different brands and different types are linked.

Different kinds of notebooks => subclasses of corresponding abstract classes:

test class
Advantages and disadvantages of bridge mode

advantage

  • Separation of abstraction and implementation, strong scalability
  • In line with the open-closed principle
  • Comply with the principle of synthesis and reuse
  • Its implementation details are transparent to customers

shortcoming

  • Since the aggregation relationship is established at the abstraction layer, developers are required to design and program for abstraction, and can correctly identify the two independently changing dimensions in the system, which increases the difficulty of understanding and designing the system.

7. Combination mode

In real life, there are many “part-whole” relationships, for example, departments and colleges in a university, departments and branches in a head office, books and school bags in school supplies, clothes and wardrobes in daily necessities, and Pots and pans etc. in the kitchen. This is also true in software development, for example, files and folders in the file system, simple controls and container controls in form programs, and so on. The processing of these simple objects and composite objects is very convenient if the composition mode is used.

The basic structure of the composition mode

  • Abstract component (Component) role: Its main role is to declare public interfaces for leaf and branch components and implement their default behavior. In the transparent composition mode, the abstract component also declares the interface for accessing and managing subclasses; in the safe composition mode, the interface for accessing and managing subclasses is not declared, and the management work is done by the branch component. (General abstract class or interface, defining some common methods, such as adding, deleting)
  • Leaf component (Leaf) role: is a leaf node object in the composition, it has no child nodes, and is used to inherit or implement abstract components.
  • Composite role/intermediate component: is the branch node object in the composition, which has child nodes for inheriting and implementing abstract components. Its main function is to store and manage sub-components, usually including Add(), Remove(), GetChild() and other methods

The basic code structure of the combined pattern

abstract component

leaf component
branch component
test class

Case requirements

It is known that a company has multiple departments, and there are multiple employees under multiple departments. Please do not list all the departments and everyone.

Organizational composition => corresponding Component role

Company => corresponding to Composite role

Department => corresponding to Composite role

Employee => corresponds to the Leaf role

test code

Advantages and disadvantages of combined mode

advantage

  • The composition mode allows client code to handle single objects and composite objects consistently, regardless of whether it is dealing with a single object or a composite object, which simplifies client code;
  • It is easier to add new objects in the composition body, and the client will not change the source code due to the addition of new objects, which satisfies the “open-closed principle”;

shortcoming

  • The design is more complex, and the client needs to spend more time clarifying the hierarchical relationship between classes;
  • It is not easy to confine the components in the container;
  • It is not easy to add new functions of components by means of inheritance;

Leave a Comment

Your email address will not be published. Required fields are marked *