欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式1——策略模式

程序员文章站 2022-06-13 13:50:26
...

这次阅读HeadFirst这本书的读书笔记,就想把学到的写成博客与之分享, 第一次写博客,如有错误欢迎纠错。

1.1定义

定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户

1.2引例(模拟鸭子应用)

需求: 系统中会出现很多鸭子,一边游泳,一边呱呱叫


1.2.1 通过超类和继承设计

其他不同的鸭子也像图中的两种鸭子一样,继承Duck超类。
每个鸭子子类负责实现自己的display()方法。
设计模式1——策略模式

可以看出鸭子:
共同点:①游泳 ②呱呱叫。
不同点:外表不同。
实现方式:通过继承超类Duck,其中超类中quack()swim()方法都是相同,在超类Duck中进行实现。display()方法不同的鸭子子类实现方式不同,因此将display()方法设计为抽象类。

追加需求:提高竞争力,要求鸭子会飞。


1.2.2 超类增加方法

做法:直接在超类增加fly()方法。
设计模式1——策略模式

问题:屏幕上很多橡皮鸭也在飞,不是所有鸭子都会飞。


1.2.3 利用接口解决

做法:将fly和quack动作单独提取出来,做成接口:flyablequackable接口。换句话讲就是将鸭子共同的特点保留在超类,将不同的特点进行提取做成不同的接口。不同鸭子的子类根据需实现相应的接口。
设计模式1——策略模式

问题:如果是fly的方式有很多,可以用翅膀,飞行器等等,quack方式也有很多,比如呱呱叫,吱吱叫等等,这样设计会出现大量的代码需要改写。


恰好现在有一种设计原则适用于这个问题。

设计原则:找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混合在一起。


1.2.4 设计鸭子的行为

1.分析鸭子的行为
找出变化的和不会变化的行为。可以看出鸭子会变化的行为目前有两个:fly和quack。不会变的行为是swim,所有的鸭子都会游泳。从图4中可以看出,fly和quack行为不单单只有一种,
设计模式1——策略模式
2.设计鸭子的行为

设计原则:针对接口编程,而不是针对实现编程。


这次不让鸭子的子类去实现行为的接口,而是用不同的行为类去实现这些接口。
以前是的做法是让超类去实现或者使用接口让子类自行实现,这两种做法都依赖于“实现”。设计没有弹性。
现在的设计不会被“实现”绑死。换句话说,具体的实现都编写在了实现FlyBehavior和quackBehavior的类中。
设计模式1——策略模式

1.2.4 总设计

(1)Duck超类变成抽象类,又添加了两个成员变量,FlyBehavior和QuackBehavior两个。
(2)增加4个方法:performFly(),performQuack(),setFlyBehavior()setQuackBehavior()
(3)两个perform方法分别调用接口中的fly()quack()方法。 两个set方法是分别设置两个成员变量FlyBehavior和QuackBehavior。
(5)将display()方法作为抽象方法进行使用。

设计模式1——策略模式

(6)其他鸭子的子类通过继承Duck超类,并在构造方法中设置成员变量。以MallardDuck构造方法为例,这样MallardDuck就实现了不会飞,呱呱叫的行为。

	MallardDuck (){
		flyBehavior=new FlyNoWay();
		quackBehavior=new Quack();
	}

图6中的封装飞行行为和封装叫行为都有不同的实现,这就避免了面对“实现”编程,通过组合来编程,这样更加灵活。

设计原则:多用组合,少用继承。


1.3代码

点击进入github源码地址>>>

(1)Duck 抽象类:

public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {
    }

    public abstract void display();

    public void performFly() {
        flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }

    public void swim() {
        System.out.println("All ducks float,even decoys");
    }

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }

}

(2) 鸭子子类(只写了两个子类实现)

//MallardDuck 子类
public class MallardDuck extends Duck {
    public MallardDuck() {
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    public void display() {
        System.out.println("I am a real Mallard duck");
    }


    public static void main(String[] args) {
        Duck mallard = new MallardDuck();
        mallard.performFly();
        mallard.performQuack();
    }
}

//ModelDuck 子类
public class ModelDuck extends Duck {

    public ModelDuck(){
        flyBehavior=new FlyNoWay();
        quackBehavior=new Quack();
    }
    public void display() {
        System.out.println("I am a model duck");
    }

    public static void main(String[] args) {
        Duck model =new MallardDuck();
        model.performFly();
        model.setFlyBehavior(new FlyRocketPowered());
        model.performFly();
    }
}

(3) FlyBehavior 接口及行为类

//FlyBehavior 接口
public interface FlyBehavior {
    void fly();
}


public class FlyNoWay implements FlyBehavior {
    public void fly() {
        System.out.println("I can not fly");
    }
}
//添加了一个用火箭飞行的行为
public class FlyRocketPowered implements FlyBehavior {
    public void fly() {
        System.out.println("I am flying with a rocket");
    }
}

public class FlyWithWings implements FlyBehavior {
    public void fly() {
        System.out.println("I am flying");
    }
}

(4)QuackBehavior接口及行为类

//QuackBehavior接口
public interface QuackBehavior {
    void quack();
}

public class MuteQuack implements QuackBehavior {
    public void quack() {
        System.out.println("<< Silence>>");
    }
}


public class Quack implements QuackBehavior {
    public void quack() {
        System.out.println("Quack!");
    }
}


public class Squeak implements QuackBehavior {
    public void quack() {
        System.out.println("Squeak");
    }
}