Hello everyone, I am xiao CAI, a desire to do CAI Not CAI xiao CAI in the Internet industry. Soft but just, soft praise, white piao just! Ghost ~ remember to give me a three – even oh!

This paper mainly introduces structural pattern in software design pattern

Refer to it if necessary

If it is helpful, do not forget the Sunday

Wechat public number has been opened, xiao CAI Liang, did not pay attention to the students remember to pay attention to oh!

After the introduction of several creation modes, I wonder if the way of creating objects has become more smooth. If not, it is better to learn a structural model today, know yourself and know your opponent to win every battle, clear object is what structure can better create!

Let’s start off as usual, but let’s be clear about what we’re going to learn today:

Design patterns

I. Structural mode

The structural pattern describes how to arrange post-class objects into a larger structure. It is divided into the class structural pattern and the object structural pattern. The former uses inheritance to organize interfaces and classes, while the latter uses composition or aggregation to combine objects.

Because the coupling degree of combinatorial or aggregative relation is lower than that of inheritance relation and meets the “composite reuse principle”, object structural pattern has more flexibility than class structural pattern.

Since we’ve seen that there are seven architectural patterns, let’s look at the first design pattern, the proxy pattern

1) Proxy mode

When, for some reason, an object needs to be provided with a proxy to control access to that object, the access object is not suitable or cannot directly reference the target object. The proxy object acts as an intermediary between the access object and the target object

Proxy mode as a development we certainly will not feel strange, JDK proxy, CGLib proxy casually come. Proxies in Java can be divided into static proxies and dynamic proxies according to the actual generation of proxy classes.

  • Static proxies are generated at compile time
  • Dynamic proxies are dynamically generated at Java runtime

Dynamic proxy is divided into JDK dynamic proxy and CGLib proxy

1. Static proxy

Let’s combine the UML diagram of the static proxy mode to understand:

You can see that the static proxy mode has three roles, which are:

  • Abstract Subject class: Business methods that declare real topics and proxy object implementations through interfaces or abstract classes.
  • Real Subject class: Implements the concrete business in an abstract topic, is the Real object represented by the proxy object, and is the object ultimately referenced.
  • Proxy class: Implements abstract topics, provides the same interface as real topics, contains references to real topics, and can access, control, or extend the functionality of real topics.

For example, if we need to take a train before, we need to go to the railway station to buy a ticket, but the railway station is far away and we have to take a bus to the railway station. If there are more than one person, we have to queue up, which is obviously very inconvenient. At this time, there are train stations, through which we can buy tickets directly.

The code is as follows:

As can be seen from the above code, the test class directly accesses the ProxyStation, which acts as an intermediary between accessing the object and the target object, and can also add abstract methods (service charge).

2. Dynamic proxy
(1) JDK dynamic proxy

In JDK dynamic Proxy, the abstract Subject and the RealSubject are unchanged, we need to change the Proxy Proxy, static to dynamic, and then the client call method changes, the code is as follows:

We see in the code that ProxyStation does not need to implement the SellTicket interface, but is this really the case? If you are interested, you can compile and view the structure of the proxy class. Here I directly say the conclusion:

In fact, ProxyStation is not a Proxy class mentioned in the Proxy mode, but a Proxy class created through Proxy. It implements the SellTicket interface and provides anonymous inner class objects to be passed to the parent class. Then the sell() method called by the Proxy object in the test class actually executes the Sell () method in the Proxy class according to the characteristics of polymorphism, so the output of the agent charging agent fee will appear.

If we do not define SellTicket, but RailwayStation, then JDK dynamic proxy is not applicable, because it must define the interface and proxy the interface. Then we need to use CGLib dynamic proxy at this time.

(2) CGLib dynamic proxy

Since CGLib is a third-party toolkit, we need to introduce dependencies first:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
Copy the code

The code then makes the following changes:

The CGLib dynamic proxy actually uses the ASM open source package to load the class file of the proxy object class and modify its bytecode generation subclass to implement the proxy. Next we compare the following agents:

Static proxy and dynamic proxy:

If the number of interface methods is large, static proxies need to relay each method, while dynamic proxies move all declared methods into a centralized method of the calling processor for processing.

If an interface adds a method, the static proxy mode requires all the proxy classes to implement the method in addition to all the implementation classes, while the dynamic proxy does not.

Conclusion: Dynamic proxy is more flexible than static proxy

JDK dynamic proxy and CGLib dynamic proxy:

Prior to JDK 1.6, CGLib dynamic proxies were more efficient than JDK dynamic proxies. However, after the JDK dynamic proxies were optimized in later versions, JDK proxies were more efficient than CGLib dynamic proxies in the case of fewer calls, and only when a large number of calls were made. JDK1.6 and JDK1.7 are slightly less efficient than CGLib agents, but by JDK1.8, JDK agents are more efficient than CGLib agents.

Conclusion: CGLib dynamic proxies cannot be used to proxy classes or methods that are declared final. JDK dynamic proxies cannot be used to proxy classes that do not have interfaces.

2) Adapter mode

Converting the interface of one class to another that the customer wants makes it possible for classes that would otherwise not work together due to interface incompatibilities

Adapter mode is about adaptation of two words, our life of mobile phone charger (voltage conversion), card reader is the use of the adapter mode.

The adapter pattern is divided into the class adapter pattern and the object adapter pattern. The former is more coupled than the latter, so it is less used.

Let’s summarize several roles in the adapter pattern:

  • Target: Indicates the interface expected by current system services. It can be an abstract class or interface
  • Adaptee: It is a component interface in an existing component library that is accessed and adapted
  • Adapter class: It is a converter. By integrating or referring to the Adapter object, the Adapter source interface is converted into the target interface, so that customers can access the Adapter according to the format of the target interface
1. Adapter-like pattern

The first step is to define an adapter class that implements the business interface of the current system while inheriting components that already exist in the existing component library

Let’s take an example:

An existing computer can only read SD cards, but now we only have TF cards. If we need to read TF cards, we need to use the adapter mode to create a card reader (adapter) to read out the contents of TF cards.

Let’s copy the UML diagram above:

There is little difference, except that there are two more implementation classes, and then we can write the code:

In terms of the functionality of the code, class adapters do do what we want them to do, but in principle they violate the principle of composite reuse, which leads to the problem that they are only available if the client has an interface specification, but not otherwise.

What? If you don’t know the principles of composite reuse, go over them. Software design principles.

2. Object adapter pattern

The object adapter pattern can be used to introduce components already implemented in an existing component library into the adapter, which also implements the business interface of the current system

What does this mean? In fact, it is to change the inheritance relationship into the aggregation relationship, as shown in the UML diagram below:

Then modify part of the code as follows:

3) Decorator mode

A pattern that dynamically adds some responsibility (additional functionality) to an object without changing the structure of the existing object

There are several roles in decorator mode:

  • Abstract Component: Defines an abstract interface to specify objects that are ready to receive additional responsibilities
  • ConcreteComponent: Implement abstract artifacts, adding responsibilities to them by decorating roles
  • Decorator: Inherits or implements an abstract artifact and contains instances of the concrete artifact that can be subclassed to extend its functionality
  • ConcreteDecorator: A method for implementing abstract decorators and adding additional responsibilities to concrete component objects

Let’s take chow mein as an example. We can add eggs or meat to chow mein. Of course, the price of these two materials is definitely different.

Then we use code to implement:

Functionality has been perfectly implemented, so what benefits can we see from it?

  • Decorator patterns extend functionality more flexibly than inheritance and are easier to use by combining different decorator objects to obtain diverse results with different behavior states. Perfect follow the open and closed principle, inheritance is static additional responsibility, decoration is dynamic additional responsibility

  • The decorator pattern is an inherited alternative to the decorator pattern, which can dynamically extend the functionality of an implementation class

Some of you may have noticed that the proxy model is similar to the decorator model in that it can dynamically add additional responsibilities through aggregation. Here is a comparison of the static proxy pattern and decorator pattern:

The same

  • All implement the same business interface as the target class
  • Declare the target object in both classes
  • You can enhance the target method without modifying the target class

The difference between

  • The purpose is different: decorators enhance the target object, static proxies protect and hide the target object
  • The place to get the target object build is different: decorators are passed in from the outside and can be passed through constructors, and static proxies are created inside the proxy class to hide the target object

4) Bridge mode

Separate the abstraction from the implementation so that they can vary independently. It is realized by using combinatorial relation instead of inheritance relation, thus reducing the coupling degree of abstraction and realization of these two variable dimensions

If there is a requirement we need to create different shapes (rectangle, circle, square), each shape should have a different color (red, white, black). When we don’t think too much about it, the first solution should look something like this:

This should be the simplest implementation, but if we need to add a shape or color, then we need to create more love you class, which is similar to the factory method pattern, the result is a class explosion, so there is no optimization solution, we came up with a second implementation as follows:

This scheme is based on the actual needs of the shape and color combination, for the system with two dimensions of change (that is, two reasons for change), using the second scheme to design the system, the number of classes will be less, system expansion will be more convenient. This mode is called bridge mode, which has the advantage of reducing the coupling between classes and reducing the amount of code to be written.

Let’s look at a UML diagram of the bridge pattern:

Then let’s take a look at some of the characters:

  • Abstraction character: Defines the abstract class and contains a reference to the implemented object
  • RefinedAbstraction character: Is a subclass of abstraction character that implements the business methods in the parent class and instantiates the business methods in the character through composition calls
  • Implementor Role: Defines an interface that implements the role for extended abstract role invocation
  • ConcreteImplementor Roles: Provides a concrete implementation of the instantiated role interface

Let’s take an example to deepen our understanding.

There are two sizes of brushes, big brushes and small brushes, and we need to be able to draw three colors (red, yellow and blue). If we use traditional crayons, we need 2*3=6 brushes. If we change the brushes to paint pens, we only need 3 boxes of paint and 2 brushes

The UML diagram is as follows:

The code is as follows:

With the above examples in mind, let’s also examine the advantages and disadvantages of the bridge pattern

Advantages:

  • The bridge mode improves the scalability of the system by extending one of the two varying dimensions without modifying the original system
  • Implementation details are transparent to customers and can be hidden from users

Disadvantages:

  • The introduction of bridge pattern will increase the difficulty of system understanding and design, because the aggregation association relationship is established in the abstraction layer, requiring developers to design and program for abstraction
  • Bridge mode requires the correct identification of two independent dimensions in the system, so its application range has certain limitations

5) Appearance mode

Appearance model is also known as facade pattern, it is a kind of by multiple complex subsystem provides a consistent interface, and makes the subsystem easier to access pattern, the pattern of foreign has a unified interface, external applications don’t need to care about the internal subsystem of the specific details, this will greatly reduce the complexity of the application, improves the maintainability of the program

In fact, the simplest example in life is the stock and fund. Some people will not fry stocks, this time the fund is a good helper, it will decentralize the investor’s capital, by professional managers to manage, investment in stocks, bonds, foreign exchange and other fields, and the fund investment returns to the holder all, management agencies charge a certain proportion of trusteeship management costs.

Appearance pattern is a typical application of Demeter's rule

Before using appearance mode:

After using appearance mode:

It is also easy to derive UML diagrams if you understand the relationships above:

There are several roles in appearance mode:

  • Facade Role: Provides a common interface externally for multiple subsystems
  • SubSystem role: Implements part of the functionality of the system, which can be accessed by customers through the facade role

Let’s take an example to illustrate it.

Xiaomi’s ecology is now very good to use, just need us to xiao Ai student speaker (Facade) voice control can control the smart home (light, air conditioning, curtain — SubSystem), which is actually to use the appearance model.

The code implementation is as follows:

This is to use the appearance mode, the customer is different with a specific home interaction, directly with the speaker interaction, and then let us pick a pick the advantages and disadvantages of the appearance mode!

Advantages:

  1. The coupling degree between subsystem and client is reduced, so that the change of subsystem does not affect the client class that calls it
  2. Shielding subsystem components from the customer reduces the number of objects the customer processes and makes the subsystem easier to use

Disadvantages:

  1. Inconsistent with the principle of open and close, more trouble to modify

6) Combination mode

The composite pattern, also known as the global pattern, is used to treat a group of similar objects as a single object. The composite pattern combines objects based on a tree structure, which is used to represent both part and whole hierarchies. This type of design pattern is a structural pattern that creates a tree structure of groups of objects.

Text to see the trouble, with a picture you know

This is a file system, and this structure is also called a tree structure. This is where the combination mode is used.

Composite, which combines objects into a tree structure to represent a partial-whole hierarchy. Users can use single objects and Composite objects consistently. So when our case is a tree structure or a partial-whole relationship, we can consider using a composite pattern.

The combined mode has two different implementations, namely transparent mode and security mode, in which the roles are consistent as follows:

  • Abstract root node (Component) roles: Define common methods and properties for objects at all levels of the system. Some default behaviors and properties can be predefined
  • Composite role: defines the behavior of branch nodes, stores child nodes, and combines branch nodes and leaf nodes to form a tree structure
  • Leaf node (Leaf) role: Leaf node object, which has no branches under it and is the smallest unit for system-level traversal
1. Transparent mode

Let’s take a look at a UML diagram of the transparent pattern:

Transparent mode is to use the method into the abstract class, whether the branch object or the leaf object has the same structure, code as follows:

The advantage of this is that Leaf nodes and branch nodes are indistishable to the outside world, and they have exactly the same behavior interface, but the Leaf class itself does not have add() and remove() methods, so it makes no sense to implement it, which leads to another pattern. The combination mode — safe mode.

2. Safe mode

The UML diagram for the security pattern is as follows:

The safe mode is to completely separate the branch node from the leaf node, and the branch node has its own method for combination, which is safer. The code implementation is as follows:

In this way, because of the lack of transparency, leaf nodes and branch nodes will not have the same interface, the client calls need to make corresponding judgments, not completely heap abstract programming, must treat leaf and container components differently.

7) Enjoy yuan mode

Sharing technology is used to efficiently support reuse of a large number of fine-grained objects. It greatly reduces the number of objects to be created by sharing existing objects, avoids the overhead of a large number of similar objects, and improves the utilization of system resources.

** There are two states in Flyweight mode:

  • Internal state, shareable parts that do not change as the environment changes
  • The non-shareable part of the external state that changes with the environment

The key to realize the sharing mode is to distinguish the two states in the application and externalize the external state.

Share mode in the development of the operation to a lot of scenarios, the first thing that can think of is a variety of pool technology, thread pool, database connection pool, String constant pool and so on, so share mode is an important way to achieve pool technology.

So the use of the share pattern is simple: reduce object creation

There are several roles in the share mode:

  • Flyweight role: Usually an interface or abstract class that declares methods common to the concrete Flyweight metaclass that provide external data (internal state) and set external data (external state) through these methods.
  • ConcreteFlyweight role: This implements an abstract meta-class, called a meta-object, that provides storage space for internal state in a concrete meta-class. Typically, concrete meta-classes can be designed in conjunction with the singleton pattern, providing a unique meta-object for each concrete meta-class
  • UnsharedFlyweight role: Not all subclasses of the abstract flyweight metaclass need to be shared. Subclasses that cannot be shared can be designed to be unshared concrete metaclass. An object that does not share a concrete meta-class can be created by instantiation
  • FlyweightFactory roles: Responsible for creating and managing weightfactory roles. When a customer object requests a privilege object, the privilege factory checks to see if there is one in the system that meets the requirement, provides it to the customer if there is one, and creates a new privilege object if there is none

Next we use code to implement:

In this way, the simple realization of the yuan model, we used to pick a pick yuan model advantages and disadvantages

Advantages:

  • Greatly reduces the number of similar or identical objects in memory, saving system resources and improving system performance
  • The external state in the share mode is relatively independent and does not affect the internal state

Disadvantages:

In order to make the object can be shared, it is necessary to externalize part of the state of the shared object, separate the internal state from the external state, and make the program logic complicated

END

This is the end of the structural pattern, but not the end of the software design pattern. The behavioral pattern is on its way!

Pay attention to the small vegetables do not get lost, the road is long and small vegetables with you to seek!

Today you work harder, tomorrow you will be able to say less words!

I am xiao CAI, a man who studies with you. 💋

Wechat public number has been opened, xiao CAI Liang, did not pay attention to the students remember to pay attention to oh!