Click “like” to see, form a habit, the public account search [dime technology] pay attention to more original technical articles. This article has been included in GitHub org_Hejianhui /JavaStudy.

preface

  • 23 design modes for shorthand
  • The singleton pattern
  • Factory Method pattern
  • Abstract Factory pattern
  • The Builder/Builder pattern
  • Prototype mode
  • Flyweight mode
  • The facade pattern
  • Updates continue at……

Here are 23 design patterns to memorize quicklyAdapter mode, the adapter mode containsClass adaptor patternandObject for the adapter schema.

The schema definition

Converts the interface of a class to another interface that the client expects. The Adapter pattern enables classes to work together that would otherwise not work together due to interface incompatibilities.

Adapter patterns come in the form of: adapter patterns for classes & adapter patterns for objects.

Class adaptor pattern

The adapter pattern for a class converts the API of the adaptive class into the API of the target class.

It can be seen in the figure above:

  • Conflict: Target expects to call the operation method, but Adaptee does not (this is incompatible).
  • Solution: To enable Target to use the SpecificOperation method in the Adaptee class, we provide an intermediate Adapter class (inheriting the Target interface from the Adaptee) to connect the Adaptee API to the Target API.

Adapter and Adaptee are inherited, which determines that the Adapter pattern is class

Usage steps (code parsing)

Step 1: Create the Target interface.

interface Target {
    // This is a method that the source Adapteee class does not have
    void operation(a);
}
Copy the code

Step 2: Create the source class (Adaptee)

class Adaptee {
    public void SpecificOperation(a) {}}Copy the code

Step 3: Create Adapter classes

// The Adapter inherits from the Adaptee and implements the Target interface.
class Adapter extends Adaptee implements Target {

    // The target interface calls operation(), but the source Adaptee does not have operation().
    // So the adapter adds the method name
    But operation() is actually just the content of calling the source Adaptee SpecificOpertaion() method
    So the adapter simply wraps the SpecificOpertaion() method into operation() that Target can call
    @Override
    public void operation(a) {
        this.SpecificOperation(); }}Copy the code

Step 4: Define the specific use target class and invoke the required methods through the Adapter class to achieve the target

public class AdapterPattern {

    public static void main(String[] args) {
        Target mAdapter = newAdapter(); mAdapter.operation(); }}Copy the code

Object for the adapter schema

Like the adapter pattern for a class, the adapter pattern for an object converts the API of the adapted class into the API of the target class.

Unlike the adapter pattern of a class, the adapter pattern of an object is not connected to an Adaptee class using inheritance relationships, but to an Adaptee class using delegation relationships.

It can be seen in the figure above:

  • Conflict: Target expects to call the operation method, but Adaptee does not (this is incompatible).
  • To enable Target to use the SpecificOperation method in the Adaptee class, we provide an intermediate Adapter class (which wraps an instance of the Adaptee) that connects the Adaptee API to Target’s API.

Adapter and Adaptee are delegate relationships, which determine that the Adapter pattern is object.

Usage steps (code parsing)

Step 1: Create the Target interface.

interface Target {
    // This is a method that the source Adapteee class does not have
    void operation(a);
}
Copy the code

Step 2: Create the source class (Adaptee)

class Adaptee {
    
    public void SpecificOpertaion(a){}}Copy the code

Step 3: Create Adapter classes (not inheritance but delegation)

class Adapter implements Target{
    // Directly associated with the adapted class
    private Adaptee adaptee;

    // We can pass in the constructor the object of the class to be adapted
    public Adapter (Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void operation(a) {
        // Use the delegate method to perform special functions
        this.adaptee.SpecificOpertaion(); }}Copy the code

Step 4: Define the specific use target class and invoke the required methods through the Adapter class to achieve the target

public class AdapterPattern {
    public static void main(String[] args) {
        // Step 4: Define the specific use target class and invoke the required methods through the Adapter class to achieve the target
        // We need to create an object of the adapted class as an argument
        Target mAdapter = new Adapter(newAdaptee()); mAdapter.operation(); }}Copy the code

Compare the two adapters

  • Object adapters: Use a combination of methods that can be adapted not only to an adaptor’s class, but also to any of its subclasses.
  • Class adapter: Can only be adapted to a specific class, but it does not need to re-implement the functionality of the entire adaptor. And it can override the behavior of the adaptor;
  • Object adapter: Uses composition instead of inheritance, delegating to the adapted by writing a few more lines of code. It’s flexible;
  • Class adapter: You need one adapter and one adaptor, just one class;
  • Object adapters: Any behavior added to an adapter applies to both the adaptor and its subclasses;

.

Problem solved

From the pattern definition, we see that the adapter pattern is used to transform interfaces to resolve incompatibilities. If you think about the adapters in our real life, the most common one is the mobile phone charger, also known as the power adapter, which converts the strong AC power of the home into the weak DC power of the mobile phone. The ac is the adapter, the charger is the adapter, and the mobile phone is the customer.

Classes that would otherwise not work together due to incompatible interfaces can work together.

Patterns of

To compose (a role). role
Client You can only invoke the target interface functions and cannot use the managed adapter directly, but you can use the managed adapter indirectly through the interface transformation of the adapter.
Target Interface The interface seen by the customer that the adapter must implement to be used by the customer.
Adapter The adapter converts the adaptor interface into a target interface for the customer to use.
The Adaptee The adapter interface is incompatible with the target interface and needs to be subclassed by the adapter to be used by the customer.

Example is given to illustrate

Using the class adapter pattern here as an example, the object adapter pattern simply changes “inherit” to “delegate the Adaptee class internally” when adapting a class implementation.

Instance profiles

  • Background: Next door Lao Wang bought an imported TV set
  • Conflict: the voltage required by imported TV sets (110V) is incompatible with the standard output voltage of domestic plugs (220V)
  • Solution: set up an adapter to convert the 220V output from the plug to 110V

That is, the adapter schema for the class in the adapter schema

Using the step

Step 1: Create Target interface (desired plug) : 110V output (convert 220V to 110V)

 interface Target {

    // Convert 220V to 110V output (original plug (Adaptee) no)
    void convert_110v(a);
}
Copy the code

Step 2: Create the source class (the original plug)

class PowerPort220V{
    // The original plug can only output 220V
    public void output_220v(a){}}Copy the code

Step 3: Create Adapter classes

class Adapter220V extends PowerPort220V implements Target{
    // The desired plug requires a call to convert_110v(), but the original plug does not
    // So the adapter adds the method name
    But convert_110V () is really just the content of the output_220V () method that calls the original plug
    // So the adapter just wraps output_220v() into convert_110v() that Target can call

    @Override
    public void convert_110v(a){
        this.output_220v(); }}Copy the code

Step 4: Define the specific use target class and invoke the required methods through the Adapter class to achieve the target (no need to go through the original plug)

// Import TV
class ImportedMachine {

    @Override
    public void Work(a) {
        System.out.println("Imported TELEVISIONS operating normally"); }}// Call the required methods through the Adapter class
public class AdapterPattern {

    public static void main(String[] args) {
        Target mAdapter220V = new Adapter220V();
        ImportedMachine mImportedMachine = new ImportedMachine();

        // The user takes the imported TV and plugs in the adapter (call Convert_110v())
        Convert_110v() = Convert_110v() = Convert_110v()
        // The adapter is just a shell, providing 110V externally, but it is essentially 220V for power supplymAdapter220V.convert_110v(); mImportedMachine.Work(); }}Copy the code

The output

Imported TVS are in normal operationCopy the code

advantages

  • Transforming interfaces, adapters make incompatible interfaces compatible.
  • Decouple the client from the implementation’s interface. With adapters, clients don’t have to modify their own code each time they invoke an incompatible interface, but simply invoke the appropriate adapter.
  • Object composition design principles are used. The adaptor is packaged as a combination, and any subclass of the adaptor can be used with the same adapter.
  • Embodies the “open and closed” principle. The adapter pattern binds the client to the interface rather than the implementation, and we can use multiple adaptors to transform multiple background classes, and we can easily add new adapters.

disadvantages

  • Each adaptor requires one adaptor, and too many adaptors can increase system complexity and reduce runtime performance.
  • Implementing an adapter can take a lot of work and make development more difficult.

Application scenarios

  • Consider using the adaptor pattern when you want to use two classes that do the same or similar things, but have different interfaces.
  • ** The adapter pattern is used when you need to unify the code of the client calling the interface and the interface being called has incompatibilities. ** This allows the client to call only one interface, which is simpler, more direct, and more compact.

It is recommended to use the adapter pattern for objects as much as possible, and to use composition/aggregation more than inheritance.

Of course, specific problems specific analysis, according to the need to choose the appropriate implementation.

Application in source code

#JDK java.util.Arrays#asList() java.util.Collections#list() java.util.Collections#enumeration() java.io.InputStreamReader(InputStream) (returns a Reader) java.io.OutputStreamWriter(OutputStream) (returns a Writer) Java.util.collections #enumeration(), an adaptation from Iterator to enumeration. #Spring org.springframework.context.event.GenericApplicationListenerAdapterCopy the code

Arrays.asList()

Use tools Arrays. AsList () to convert the array collection, cannot use the modify the related methods of collection, it’s the add/remove/clear method will throw an UnsupportedOperationException anomalies.

The return object of asList is an inner array class that doesn’t implement collection modification methods. Arrays.aslist is an adaptor pattern, just a conversion interface, and the data behind it is still an array.

GenericApplicationListenerAdapter

The event model in the Spring architecture, event oriented programming can make your application more scalable, design more beautiful, more design sense, is the most common way to decouple, first look at the class diagram.ApplicationListener Event listener interface, implemented in observer mode.

GenericApplicationListener processing based on the generic event listener interfaces, provides a monitoring based on event types, as follows:

boolean supportsEventType(ResolvableType eventType);
Copy the code

Is an improved version of SmartApplicationListener.

SmartApplicationListener An event-based listener interface as follows:

boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
Copy the code

ApplicationListenerMethodAdapter GenericApplicationListener adapter implementation, as follows:

public class ApplicationListenerMethodAdapter implements GenericApplicationListener
Copy the code

As you can see, this is implemented through an adapter pattern that implements interfaces.

Java is a single inheritance. Implementing interfaces in this way can indirectly achieve multiple inheritance, which has better scalability.

SourceFilteringListener based on GenericApplicationListener SmartApplicationListener decorator pattern implementation, from the specified source screening events, call it entrusts the listener to match application event object.

GenericApplicationListenerAdapter GenericApplicationListener adapter pattern implementation.

PS: The above code is submitted to Github: github.com/Niuh-Study/…

GitHub Org_Hejianhui /JavaStudy GitHub Hejianhui /JavaStudy