设计模式之策略模式

时间:2022-05-05 00:20:54

策略模式

     最近买了一本关于java设计模式的新书《Head First 设计模式》,里面介绍了java 的23种设计模式。目前看了第一章介绍的策略模式,里面的内容很容易理解,但是让我自己用嘴说出来却又总感觉表达不是很清楚。正所谓温故知新,所以我打算把自己的理解以及书上的代码记录到这里,算是一个回顾的过程。

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

    这本书上介绍策略模式使用的是一个鸭子的对象,其中鸭子有很多属性:飞行、鸣叫、展现形式等。由于要做一个通用的鸭子对象模型,所以我们需要把把这个鸭子创建成一个抽象的对象,将所有鸭子的通用属性放在抽象类中,而将差异化的属性在继承类中实现。考虑到代码的可扩展性和后期的维护,又将继承的这种模式进行改变,将两个类结合起来使用,即组合的方式。这种做法和继承不同的地方在于,鸭子的行为不是继承来的,而是和适当行为对象“组合”来的。使用组合建立系统具有很大的弹性,不仅可将算法族封装成类,更可以“在运行时动态地改变行为”,只要组合的行为对象符合正确的接口标准即可。

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

先来一张整体设计图:


设计模式之策略模式

这张图展示了利用策略模式对鸭子对象的属性进行拆分和组合,将鸭子的飞行和鸣叫的行为委托给接口来处理,而固定属性则封装在抽象类中。

上代码:

Duck类

package com.my.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 fb){//提供动态改变飞行行为的方法

flyBehavior = fb;
}

public void setQuackBehavior(QuackBehavior qb){//提供动态改变鸣叫行为的方法
quackBehavior = qb;
}
}

FlyBehavior类

package com.my.duck;

public interface FlyBehavior {
public void fly();//所有飞行行为类必须实现的接口
}
FlyBehavior的实现

package com.my.duck;

public class FlyWithWings implements FlyBehavior {

@Override
public void fly() {
System.out.println("I'm flying !");
}
}
package com.my.duck;public class FlyNoWay implements FlyBehavior {    @Override    public void fly() {        System.out.println("I can't fly");    }}
QuackBehavior接口

package com.my.duck;

public interface QuackBehavior {
public void quack();
}
QuackBehavior实现

package com.my.duck;

public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack");
}
}
package com.my.duck;public class MuteQuack implements QuackBehavior {    @Override    public void quack() {        System.out.println("<<Silence>>");    }}
package com.my.duck;public class Squeak implements QuackBehavior {    @Override    public void quack() {        System.out.println("Squeak");    }}

新建一个模型鸭子(ModelDuck)

package com.my.duck;

public class ModelDuck extends Duck {
public ModelDuck(){
flyBehavior = new FlyNoWay();//一开始模型鸭子不会飞行
quackBehavior = new Quack();
}

@Override
public void display() {
System.out.println("I'm a model Duck");
}
}
运行函数:

package com.my.duck;

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

Duck model = new ModelDuck();
//第一次调用performFly()会被委托给flyBehavior对象(也就是FlyNoWay实例),该对象是在模型鸭构造器中设置的。
model.performFly();
//这会调用继承来的setter方法,把火箭动力飞行的行为设定到模型鸭子中。
model.setFlyBehavior(new FlyRocketPowered());
//鸭子的飞行方式将变成乘坐火箭飞行器飞行。
model.performFly();
}
}
运行效果:

设计模式之策略模式