设计模式--策略模式

时间:2022-11-11 21:59:01
    首先谈一下软件开发的一个不变真理,那就是   change ,顾客的需求会不断发生改变,不论刚开始设计的多好,一段时间后,总是需要改变和成长,客户是相当善变的。就像我接触的快速阅读,儿童时期,阅读时往往采用逐字阅读,在阅读量较小的情况下,还可以满足需求,但是,随着年龄增大,阅读量上升的情况下,逐字阅读只会妨碍你的理解,拖慢你的速度,影响你的集中力,所以必须要改变。另外这也要求程序员,我们必须要有良好的适应能力和抗压能力。

模拟一个情景,“鸭子” 假设创建会飞的鸭子,一般会在父类Duck类中定义fly()方法,其他具体的鸭子继承就可以了,但是问题来了。如果有某种鸭子不会飞怎么办,如小黄鸭,方法一,可以选择覆盖但是不做任何事,但这样会让代码多余,很笨。方法二,把fly行为单独拿出来,定义一个接口,只有一个方法,为fly(),如果鸭子能飞,则实现此接口,如果不行,则不实现此接口,这的确可以解决一部分问题,但是假如此鸭子的飞行行为是会发生改变怎么办,意味着未来你需要修改代码,或者此鸭子的飞行行为不止一种,这种方法不能很好的满足要求。
这里引出一个重要的原则,***找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混合在一起。***
这里的变化就是飞行行为,所以把它单独拿出来。每一种飞行行为都成为一个类。一般我们是把一个对象抽象为一个类,但是,在这里,我们把行为抽象出来。
另一个原则,***针对接口编程,而不是针对实现编程***,(这里的接口是宽泛的概念,具体指抽象类或接口),因此为飞行类定义一个fly接口。每个具体的飞行类实现此接口。
另外一个概念,“有一个”比“是一个”。前一个指的是一个类有其他类的接口引用,后一个指的是类继承父类。引出一个原则:***多用组合,少用接口***。组合往往意味着委托其他对象来完成自己的事,就像你叫别人完成你要的事。
综合起来,就是鸭子类里有飞行类的接口引用,

设计模式--策略模式
上面图中Duck类中有setFlyBehavior(Fly fly){}这个赋值方法。
接下来看定义,策略模式:定义了算法族,分别封装起来,让它们之间可以互相交替,此模式让算法的变化独立于使用算法的客户。 装逼炫酷专用!
算法族,就是图中fly那部分,就是定义了具体的行为,封装为类,在Duck类中定义了引用和赋值方法,因此可以替换,想想把自己想的Duck对象,那么你是不知道具体的fly行为的。
模型:这个模式可以想成可拆卸式玩具模型,比如武器,一个人物虽然只能一次只能装一样武器,但是武器是可以拆下来,也可以换上不同的。
系统端代码:
Duck

    FlyBehavior flyBehavior;
QuackBehavior quackBehavior;

public abstract void display();

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

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

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接口
public interface FlyBehavior {

public void fly();
}

实现类

public class FlyRocketPowered implements FlyBehavior{

@Override
public void fly() {
System.out.println("I'm flying with a rocket");
}

}
public class FlyWithWings implements FlyBehavior{

@Override
public void fly() {
System.out.println("I'm flying");
}
}

客户端

public class MiniDuckSimulator {

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

Duck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}