A pattern triggered by a duck — strategy pattern

Pre knowledge:

You need to understand the of Java:

1. Packaging

2. Succession

3. Polymorphism

4. Abstraction

The first three are also called the three features of Java

Demo Description: (OO principle solution)

As we all know, an unknown duck can swim (the prophet of Chunjiang water heating duck), some ducks can fly (toy ducks, tied to aircraft / could fly in different ways), and some ducks can bark (toy ducks can also bark, but with different barks)

In fact, the first reaction is to use the inheritance method. Originally, all ducks can fly and bark. Isn't it over to let subclasses rewrite individually

But Lao Jin has to say but Suppose, as a clown duck, I don't need to be able to fly, and I don't want to fly. Why do you want me to realize the corresponding function of flying and let you fly? I'll carry the pain

Here comes the first design principle:

I Opening and closing principle

So how do you use design patterns to implement this scenario in your program?

0. Overall class diagram

First, let's take a look at the overall UML class diagram. This class diagram is automatically generated by idea. The default shortcut key is I Baidu, well, it's written in the idea shortcut key of my blog

Let's try:

It can be seen from the above that a mallardduck (mallard duck) inherits from the duck parent class, which only has the corresponding behavior attribute, and the corresponding behavior attribute is also an interface. The specific class diagram is as follows:

Two design principles are used here:

II Dependence Inversion Principle

III Combination / aggregation Reuse Principle

All right, let's go to the code

1. Specific code

1.1 about ducks

1.1. 1. Duck parent class: duck java

package firstDuck.duck;

import firstDuck.behavior.IFlyBehavior;
import firstDuck.behavior.IQuackBehavior;

/**
 * 鸭子父类(抽象)
 */
public abstract class Duck {
    /** 飞的行为 定义为接口,在运行时,持有特定行为的引用*/
    protected IFlyBehavior iFlyBehavior;
    /** 叫的行为 也是被定义为接口*/
    protected IQuackBehavior iQuqBehavior;


    public Duck() {
    }

    /**
     * 调用飞的行为去飞
     *
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 23:25
     */
    public void doFly() {
        this.iFlyBehavior.fly();
    }

    /**
     * 调用叫的行为去叫
     *
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 23:25
     */
    public void doQuack() {
        this.iQuqBehavior.quack();
    }

    /**
     * 显示外观 相当于toString
     *
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 22:54
     */
    public abstract void display();

    public void swim() {
        System.out.println("所有的鸭子都会浮在水面上~");
    }
}

1.1. 2 duck subclass (there can be many here, for example 1) mallard duck java

package firstDuck.duck.duckSon;

import firstDuck.behavior.impl.FlyWithWings;
import firstDuck.behavior.impl.Quack;
import firstDuck.duck.Duck;

/**
 * 绿头鸭
 *
 * @author 金聖聰
 * @email jinshengcong@163.com
 * @version v1.0
 * @date 2021/01/13 22:55
 */
public class MallardDuck extends Duck {

    /**
     * 绿头鸭构造器
     *
     * @return null
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 23:35
     */
    public MallardDuck() {
        /* 绿头鸭调用Quack类处理正真的呱呱叫 */
        super.iQuqBehavior = new Quack();
        /* 绿头鸭调用FlyWithWings类处理正真的飞行 */
        super.iFlyBehavior = new FlyWithWings();
    }

    public void display() {
        System.out.println("我是一个真正的绿头鸭");
    }
}

1.2 about behavior

1.2. 1. Flight behavior java

This is an interface. All flight classes implement it. All flight classes must implement the fly () method

package firstDuck.behavior;

/**
 * 飞行的行为
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public interface IFlyBehavior {
    /**
     * 飞行
     *
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 23:11
     */
    void fly();
}
1.2. 1.1 implementation class of flight behavior flynoway java
package firstDuck.behavior.impl;

import firstDuck.behavior.IFlyBehavior;

/**
 * 不能飞
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class FlyNoway implements IFlyBehavior {
    @Override
    public void fly() {
        System.out.println("我不能飞啊喂~");
    }
}

1.2. 1.2 implementation class of flight behavior flywithwings java
package firstDuck.behavior.impl;

import firstDuck.behavior.IFlyBehavior;

/**
 * 翅膀飞
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class FlyWithWings implements IFlyBehavior {
    @Override
    public void fly() {
        System.out.println("用翅膀飞~");
    }
}

1.2. 2. It's called iquckbehavior java

The calling behavior is the same. All calling classes implement it, and all calling classes must implement the quack () method

package firstDuck.behavior;

/**
 * description
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public interface IQuackBehavior {
    /**
     * 叫
     *
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 23:11
     */
    void quack();
}

1.2. 2.1 implementation class called quack java
package firstDuck.behavior.impl;

import firstDuck.behavior.IQuackBehavior;

/**
 * 鸭子嘎嘎叫
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class Quack implements IQuackBehavior {
    @Override
    public void quack() {
        System.out.println("我真鸭子,我嘎嘎叫~");
    }
}

1.2. 2.2 implementation class called squeak java
package firstDuck.behavior.impl;

import firstDuck.behavior.IQuackBehavior;

/**
 * 橡皮鸭子吱吱叫
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class Squeak implements IQuackBehavior {
    @Override
    public void quack() {
        System.out.println("我橡皮鸭子,我吱吱叫~");
    }
}

1.2. 2.3 implementation class called squeak java
package firstDuck.behavior.impl;

import firstDuck.behavior.IQuackBehavior;

/**
 * 哑巴鸭不会叫
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class MuteQuack implements IQuackBehavior {
    @Override
    public void quack() {
        System.out.println("我不会叫~~");
    }
}

1.3 testing

package firstDuck.test;

import firstDuck.duck.Duck;
import firstDuck.duck.duckSon.MallardDuck;

/**
 * 迷你鸭子模拟器 测试类
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class MiniDuckSimulator {
    public static void main(String[] args) {
        /* 绿头鸭 */
        Duck mallard = new MallardDuck();
        mallard.display();
        mallard.doFly();
        mallard.doQuack();
    }
}

Output:

Therefore, the mallard will really quack, because when constructing an instance, the constructor will initialize the inherited iquqbehavior into a new instance of quack type,

The same treatment is applied to flight behavior

3. Think about it

What's going on here in the mallard's constructor

public MallardDuck() {
        /* 绿头鸭调用Quack类处理正真的呱呱叫 */
        super.iQuqBehavior = new Quack();
        /* 绿头鸭调用FlyWithWings类处理正真的飞行 */
        super.iFlyBehavior = new FlyWithWings();
    }

According to the dependency inversion principle of the design principle introduced at the beginning, shouldn't you program for the interface? How can you program for the implementation here? Are you constructing a specific implementation class called "flying behavior" and "flying behavior"? Be reliable, old Kim~

OK, who says I'm unreliable? I'll blow your head ~[doeg. GIF]

Step by step~

At the beginning, we created a bunch of dynamic behavior attributes (actually only two) in the duck class, which are not used. Now use it

3.1 start of transformation:

3.1. The first is duck java
package firstDuck.duck;

import firstDuck.behavior.IFlyBehavior;
import firstDuck.behavior.IQuackBehavior;

/**
 * 鸭子父类(抽象)
 */
public abstract class Duck {
    /** 飞的行为 定义为接口,持有特定行为的引用*/
    protected IFlyBehavior iFlyBehavior;
    /** 叫的行为 也是被定义为接口*/
    protected IQuackBehavior iQuqBehavior;

    /**
     * 新增飞行的setter方法
     * @param iFlyBehavior 飞的行为
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/18 23:50
     */
    public void setiFlyBehavior(IFlyBehavior iFlyBehavior) {
        this.iFlyBehavior = iFlyBehavior;
    }

    /**
     * 新增叫的setter方法
     * @param iQuqBehavior 叫的行为
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/18 23:51
     */
    public void setiQuqBehavior(IQuackBehavior iQuqBehavior) {
        this.iQuqBehavior = iQuqBehavior;
    }

    public Duck() {
    }

    /**
     * 调用飞的行为去飞
     *
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 23:25
     */
    public void doFly() {
        this.iFlyBehavior.fly();
    }

    /**
     * 调用叫的行为去叫
     *
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 23:25
     */
    public void doQuack() {
        this.iQuqBehavior.quack();
    }

    /**
     * 显示外观 相当于toString
     *
     * @return void
     * @author 金聖聰
     * @email jinshengcong@163.com
     * @version v1.0
     * @date 2021/01/13 22:54
     */
    public abstract void display();

    public void swim() {
        System.out.println("所有的鸭子都会浮在水面上~");
    }
}

That is, add two setter methods to dynamically set member variables

Since then, we can dynamically call these two methods to change the behavior of ducks at any time, which is equivalent to implanting a chip in our brain and being done whatever people want ~ tut tut tut tut

Test it, test it

3.1. 2. Then create a new subclass modelduck java
package firstDuck.duck.duckSon;

import firstDuck.behavior.impl.FlyNoway;
import firstDuck.behavior.impl.MuteQuack;
import firstDuck.duck.Duck;

/**
 * description
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class ModelDuck extends Duck {
    public ModelDuck(){
        /* 一开始不会飞  */
        super.iFlyBehavior = new FlyNoway();
        /* 一开始不会叫  */
        super.iQuqBehavior = new MuteQuack();
    }

    @Override
    public void display() {
        System.out.println("我是模型鸭子");
    }
}

3.1. 3 create a new flight behavior to let the rocket fly! FlyByRocket. java
package firstDuck.behavior.impl;

import firstDuck.behavior.IFlyBehavior;

/**
 * description
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class FlyByRocket implements IFlyBehavior {
    @Override
    public void fly() {
        System.out.println("插了火箭了,上天,冲干饭鸭~");
    }
}

3.1. 4. Modify test class
package firstDuck.test;

import firstDuck.behavior.impl.FlyByRocket;
import firstDuck.duck.Duck;
import firstDuck.duck.duckSon.MallardDuck;
import firstDuck.duck.duckSon.ModelDuck;

/**
 * 迷你鸭子模拟器 测试类
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 */
public class MiniDuckSimulator {
    public static void main(String[] args) {
        /* 绿头鸭 */
        Duck mallard = new MallardDuck();
        mallard.display();
        mallard.doFly();
        mallard.doQuack();
        System.out.println();
        System.out.println("-----------改造后------------");
        Duck modelDuck = new ModelDuck();
        modelDuck.display();
        modelDuck.doQuack();
        modelDuck.doFly();
        /* 一开始是不会飞的,直到我给他插了火箭,摇身一变冲天干饭鸭  */
        modelDuck.setiFlyBehavior(new FlyByRocket());
        /* 现在插了火箭了,看看阿能飞了 */
        modelDuck.doFly();
    }
}

Operation results:

Well, congratulations ~get strategy mode

What is the final official definition of the strategic model? Back down, suitable for forcing~

How to recite, Gan?

The algorithm family is imagined as the flight mode just now. There are so many flight modes to use. Is an interface defined to encapsulate? Then, when specifically used, as long as the specific behavior of new is added to the setter method, it can be dynamically changed? The specific model duck still can't fly. Did you insert the rocket? Can you insert it or pull it out?

I didn't drive, get out~

So the mnemonic above is

The algorithm family (behavior mode) is defined and encapsulated separately (made into an interface) so that they can replace each other (dynamic set call). This mode makes the change of the algorithm (behavior) independent of the customers using the algorithm (behavior)

To sum up:

1. Opening and closing principle

Close the modification, open the development, find out the changed parts of the program, and package them independently

2. Dependency inversion

Rely on abstraction rather than concrete;

For interface / Abstract Programming, not for specific classes

3. Combined multiplexing

Use more combination and less inheritance

4. Policy mode definition

The algorithm family is defined so that they can replace each other. This pattern can make the changes of the algorithm independent of the customers using the algorithm

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>