Design mode self study notes 003_Real (decorator design mode, adapter design mode)

Posted by keeve on Mon, 07 Mar 2022 04:00:08 +0100

Design mode self study notes 003_Real (decorator design mode, adapter design mode)

1, Decorator design mode

In the previous proxy design pattern, we expanded the methods in the class. Now, a class in Wu needs to add new functions, that is, it needs to add new methods to realize new functions. The first way is to create another class to inherit this class, then rewrite the methods of this class and add new methods to realize new functions. Then the second way is to use the decorator design pattern.

The decorator design pattern is to first establish a public interface class, and then a specific class to implement the method of the interface class. If we want to add new method functions to the specific class, we will then establish a decorator class, create the instantiation object of the original class, rewrite the interface method, and use the instantiation object to call the method of the original class, Then we add new methods to the decorator class to implement the new functions.

Let's take an example of a robot. For example, a company has produced a robot that can sing and dance, but now it has received new demand and hopes to realize new functions, such as sweeping and mopping. Then, according to the principle of decorator design mode, we can design an external bone with hands and feet on the external bone, As long as it is installed on the original robot, the functions of sweeping and mopping the floor can be realized, so there is no need to redesign the robot, and the original robot can be reused. The code of the example is as follows:

public class DecoratorDesign01 {
    public static void main(String[] args) {
        DecoratorRobot robot = new DecoratorRobot(new InitialRobot());
        robot.dance();
        robot.sing();
        robot.Sweep();
        robot.Mop();
    }
}
//Common interface class
public interface Robot {
    void sing();
    void dance();
}
//Initial class
class InitialRobot implements Robot{
    @Override
    public void sing() {
        System.out.println("Robot singing");
    }

    @Override
    public void dance() {
        System.out.println("The robot is dancing");
    }
}
//Decorator class
class DecoratorRobot implements Robot{
    private InitialRobot robot;

    public DecoratorRobot(InitialRobot robot) {
        this.robot = robot;
    }

    @Override
    public void sing() {
        robot.sing();
    }

    @Override
    public void dance() {
        robot.dance();
    }

    //Add new function: sweeping the floor
    public void Sweep(){
        System.out.println("The robot is sweeping the floor");
    }
    //Add new function: mop the floor
    public void Mop(){
        System.out.println("The robot is mopping the floor");
    }
}
Output result:
The robot is dancing
 Robot singing
 The robot is sweeping the floor
 The robot is mopping the floor

2, Adapter design pattern

The main purpose of converting the interface of a class into another interface representation expected by the client is to make the two classes that you can work together that do not match the original interface work together. The alias is the wrapper design pattern.

It is mainly divided into three categories: class adapter mode, object adapter mode and interface adapter mode

The purpose is to make incompatible classes compatible.

1. Class adapter:
Then we use the example of the adapter to write a piece of code: add the current hungry waistline mobile phone charging, but the home power supply voltage is 220V, and the mobile phone charging needs 5V. In this way, we need an adapter to convert the voltage from 220V to 5V for charging. The code is as follows:

//Adapted class
public class Voltage220V {
    //Output voltage of 220 volts
    public int output220V(){
        int src = 220;
        System.out.println("Voltage"+src+"Crouch");
        return src;
    }
}

//Adapter interface
public interface Voltage5V {
    int output5V();
}

//adapter class 
public class VoltageAdapter1 extends Voltage220V implements Voltage5V{
    @Override
    public int output5V() {
        //Obtain 220V voltage
        int srcV = output220V();
        int dstV = srcV / 44;
        return dstV;
    }
}

public class Phone {
    //Charging method
    public void charging(Voltage5V voltage5V){
        if(voltage5V.output5V() == 5){
            System.out.println("The voltage is 5 V,Can charge");
        }else if(voltage5V.output5V() > 5){
            System.out.println("The voltage is too high to charge");
        }
    }
}

public class AdapterDesign001 {
    public static void main(String[] args) {
        System.out.println("=== Class adapter mode ===");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter1());
    }
}

2. Object adapter
The class adapter design pattern solves the problem of interface incompatibility. However, generally speaking, if we can not use inheritance in programming, we should not use inheritance relationship. Class II adapters need adapter classes to inherit the adapted classes. Therefore, in order to solve this problem, when object adapters appear, we do not need to inherit the adapted classes, You can directly create an instance of the adapted class in the adapter class. If you improve the above example, you only need to change the adapter class, that is, remove the inheritance relationship and create an instantiation object of Voltage220V class in the adapter class for use by the adapter. The code is as follows:

//Adapted class
public class Voltage220V {
    //Output voltage of 220 volts
    public int output220V(){
        int src = 220;
        System.out.println("Voltage"+src+"Crouch");
        return src;
    }
}

//Adapter interface
public interface Voltage5V {
    int output5V();
}

//adapter class 
public class VoltageAdapter1 implements Voltage5V{
    private Voltage220V voltage220V = new Voltage220V();

    public VoltageAdapter1(Voltage220V voltage220V) {
        this.voltage220V = voltage220V;
    }

    @Override
    public int output5V() {
        //Obtain 220V voltage
        int srcV = voltage220V.output220V();
        int dstV = srcV / 44;
        return dstV;
    }
}

public class Phone {
    //Charging method
    public void charging(Voltage5V voltage5V){
        if(voltage5V.output5V() == 5){
            System.out.println("The voltage is 5 V,Can charge");
        }else if(voltage5V.output5V() > 5){
            System.out.println("The voltage is too high to charge");
        }
    }
}

public class AdapterDesign001 {
    public static void main(String[] args) {
        System.out.println("=== Object Adapter Pattern  ===");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter1(new Voltage220V()));
    }
}

According to the "composite Reuse Principle", try to use association relationship instead of inheritance relationship in the system.
Object adapter pattern is a common pattern of adapter pattern.

3. Interface adapter
Interface adapter mode: for example, there is an interface with many methods, fun1(), fun2(), fun3(), fun4(). For example, there are four more methods, but now we only need to use one or two of them, and the other methods are not required. But if a class implements the interface, all the methods in the interface must be implemented, and unnecessary code will be generated. The solution of the interface adapter is to create an abstract class to implement all the methods of the interface, But they are all empty implementations. Only methods and method bodies are spatio-temporal. Then when we are using them, we can directly create an abstract class and optionally rewrite the methods in it. The code is as follows:

//Interface class
public interface interface2 {
    void fun1();
    void fun2();
    void fun3();
    void fun4();
}
//An abstract class that implements all interfaces empty
public class abstractClass implements interface2{
    @Override
    public void fun1() {

    }

    @Override
    public void fun2() {

    }

    @Override
    public void fun3() {

    }

    @Override
    public void fun4() {

    }
}

public class Client2 {
    public static void main(String[] args) {
        abstractClass class1 = new abstractClass(){
            @Override
            public void fun2() {
                System.out.println("Called fun1()method");
            }
        };
        class1.fun2();

    }
}

Topics: Java