preface

Both the adapter pattern and the decorator pattern combine classes or objects to produce a larger structure to meet higher-level logical requirements. The decorative pattern is a special application of the proxy pattern, which focuses on strengthening and weakening the function of the class. The adapter pattern focuses on the process of transforming the source role.

directory

1. Adapter mode

1, define,

Structural design patterns focus on the combination of objects, while creative design patterns focus on the internal structure of an object.

The key to the adapter pattern is transformation, transforming the source role into the target role.

Specific definitions are as follows:

Transform the interface of one class into the interface that the client expects, so that two classes that would otherwise not work together due to interface mismatches can work together.

2. Analysis of mode principle

There are three key roles

  • The target class, the abstract class or interface that the adapter class is going to adapt to, is what interface does the other class need to be converted to

  • The adapter class, which you want to convert into the target role, is a brand new role wrapped by the adapter

  • A concrete adapter class can be either an inner class or an outer class

It’s easy to understand when you look at the code

Public class Adaptee{public void adapteeEat(){system.out.println (" food is too expensive to eat "); }} public void targetBuyThings(); } public class AdapteTarget implements Target{@override public void targetBugThings(){ System.out.println(" things are too expensive to buy "); Public class Adapter extends Adaptee implements Target{@override public void targetBugThings(){ super.adapteeEat(); System.out.println(" things are too expensive to buy "); Public class Client{public static void main(String[] args){Target Target = new Adapter(); target.targetBuyThings(); }}Copy the code

Code is very simple, the use of the interface, to achieve the purpose of multiple inheritance, the realization of the association between different classes, can be understood as the middle of the two classes encapsulated together.

What if our Adaptee information comes from a different class? How to handle this, as shown in the constructor or in the get and set methods

public class Adapter implements Target{ private Adaptee adaptee1; private Adaptee adaptee2; public Adapter(Adaptee adaptee1,Adaptee adaptee2){ this.adaptee1 = adaptee1; this.adaptee2 = adaptee2; } @Override public void targetBugThings(){ super.adapteeEat(); System.out.println(" things are too expensive to buy "); }}Copy the code

You’ve probably heard about object adapters and class adapters, what’s the difference between these two types of adapters?

  • Class adapters are interclass inheritance

  • An object adapter is a composition relationship of objects

3. Usage Scenarios

There are many scenarios, but just keep in mind that the adapter pattern is probably the most appropriate pattern when you need to modify an interface that is already in production, such as when the system is extended and needs to use an existing or newly created class. Or when different data formats and protocols need to be transformed. For example, API gateway often needs to adapt and transform data and communication protocols for different clients such as iOS, Android and H5. In this case, gateway is an adapter.

The adapter pattern is typically used to solve service project problems and is best not considered in the detail phase, since the main scenario is in extension applications.

4, strengths,

  • Let two classes that have no task relationship run together

  • – Added class transparency. New functionality in a specific adaptor class affects only the adaptor class, but is transparent to client classes that use the target class interface

  • Improved class reusability

  • Conforms to the open closed principle

  • Satisfies the Richter substitution principle

5 and disadvantages

  • Only one abstract class or interface can be configured at a time

  • Excessive nesting can lead to bloated interfaces

  • The Target interface depends on too many Adapter interfaces. If the Target interface is changed, all Adapter interfaces must be changed. If the Target method is changed, all Adapter interfaces must be changed. This corresponds to many of the cases mentioned earlier with Adaptee

Two, decoration mode

1, define,

Dynamically adds additional responsibilities to an object

2. Pattern analysis

Public abstract class Component{// public abstract void operate(); } public class ConcreteComponent extends Component{@override public void operate(){system.out.println () car"); Public Abstract class Decorator extends Component{private Component Component = null; public Decorator(Component component){ this.component = component; } @override public void operate(){this.component.operate(); }} public Class ConcreteDecorator1 extends Decorator{puiblic ConcreteDecorator1(Component Component){  super(component); } private void method1(){system.out.println ("method1 modifier "); } public void operate(){this.method1(); super.operate(); }}Copy the code

The simplest way to think about it is that one class holds another class, and the method calls in the new class can operate on the methods of the other class. Note that the methods in this case are the operate methods. This pattern is also an alternative to inheritance

The execution order of the original method and the decorator method is fixed in the specific decorator class, and multiple execution orders can be achieved through method overloading

3. Usage Scenarios

  • You need to dynamically extend the functionality of a class or add additional functionality to a class

  • Modifications need to be made for a number of sibling classes

  • A scenario in which expansion capabilities are added by way of sequential combination wrapping

For example, data reporting, burying, new functions need to be more detailed, you can consider decorator mode

4, strengths,

  • The decorator and decorated classes can evolve independently and are not coupled to each other (see the concrete code above, both classes implement the base class interface)

  • Dynamic extension function

  • You can combine several behaviors on a unified behavior

  • Meet the single responsibility principle

5 and disadvantages

  • The code needs to be changed when a decorator is removed from the call chain. Why? Look at the following code

    Component component = new ConcreteComponent(); ConcreteDecorator1(Component) = New ConcreteDecorator1(Component); // Secondary modifier Component = New ConcreteDecorator2(Component); // Run component.operate();Copy the code
  • If there are too many decorated classes, it will increase the difficulty of understanding the code, subsequent maintenance and troubleshooting

Third, the difference between

Both the adapter pattern and decorator pattern are structural patterns and both function as packaging.

While the decorator pattern emphasizes dynamic extension functionality, all decorator classes have a common parent, the adapter pattern focuses on transformation, transforming source roles into target roles through inheritance and implementation.