您的位置:首页 > 其它

设计模式学习之——策略模式

2016-07-17 19:21 429 查看
使用设计模式最好的方式:把设计模式装进脑袋里面,然后在你的设计和已有的应用中,寻找何处可以使用它们。

设计模式是一种前人踩过的坑,之后总结下来的编程经验,也就是说这样做通常比较好。我们学习这种经验,以便在我们以后的项目中避免很多问题。

应用场景

举个例子,一个鸭子类。

原来有一些行为,现在要加入飞行的方法。那么怎么做才是最好的解决方法呢?

注意,并不是所有的鸭子都能飞。

所以直接在父类里面加进去飞行方法是有问题的。

这个飞行动作 是可变的,并不是每种都有的。

涉及到维护的时候,为了复用而使用继承,结局并不好。

对超类进行局部修改,影响层面是全局的。

如果使用接口,那么虽然解决了只有会飞的鸭子才能飞的问题,但是呢,却造成了原来所有的实现都要修改和大量的代码冗余。

解决办法

每次新的需求来了,需要改变的部分,就是要封装起来的部分。

核心思想:把会变化的部分取出并封装起来 ,以便以后可以轻易地改动或者扩展此部分,而不影响其他不需要变化的部分。

把飞行的行为作为一个借口,依附于超级鸭子父类

鸭子的子类使用接口所表示的行为,不会绑死在鸭子的子类里面。

下面是全部代码

首先是 duck类

public abstract class Duck {
public Duck(){

};
FlyBehavior flyBehavior;

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

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

public void swim(){
System.out.println("所有鸭子都可以游泳");
}


}

接下来是飞行接口。

public interface FlyBehavior {
public void fly();


}

实现飞行借口的类

public class FlyWithNoWay  implements FlyBehavior{

@Override
public void fly() {
System.out.println("我不会飞!");

}


}

另一个

public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("翅膀飞");
}


}

最后我们真正用到的鸭子

public class MallardDuck extends Duck {

public MallardDuck() {
flyBehavior=new FlyWithWings();

}


}

测试类

public class TestFly {
public static void main(String[] args) {
Duck duck=new MallardDuck();
duck.performFly();
duck.setFlyBehavior(new FlyWithNoWay());
duck.performFly();
}
}


运行结果

翅膀飞

我不会飞!

维护以及优点

假如说以后加入一个喷气鸭子,怎么办呢?

public class FlywithRocket implements FlyBehavior {

@Override
public void fly() {
System.out.println("喷气飞");
}
}


public class TestFly {
public static void main(String[] args) {
Duck duck=new MallardDuck();
duck.performFly();
duck.setFlyBehavior(new FlywithRocket());//喷气飞
duck.performFly();
}


}

那么假如要加入一个新的行为,比如说eat ,这个行为至少橡皮鸭子就是不能吃的。

所以首先要新写一个eat的接口。

public interface EatBehavior {
public void eat();


}

实现接口的具体吃法

public class EatWithGlass implements EatBehavior {
@Override
public void eat() {
System.out.println("吃草");
}
}


public class EatWithNothing implements EatBehavior {
@Override
public void eat() {
System.out.println("什么都不吃");
}


}

接下来修改原来的DUCK类

public abstract class Duck {
public Duck(){

};
FlyBehavior flyBehavior;
EatBehavior eatBehavior;

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

public void setEatBehavior(EatBehavior eatBehavior) {
this.eatBehavior = eatBehavior;
}

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

public void performEat(){
eatBehavior.eat();
}

public void swim(){
System.out.println("所有鸭子都可以游泳");
}


}

测试类

public class TestEat {

public static void main(String[] args) {
Duck duck=new MallardDuck();
duck.setEatBehavior(new EatWithNothing());
duck.performEat();
duck.setEatBehavior(new EatWithGlass());
duck.performEat();
}


}

这样就可以动态的改变新的属性了。

那么最关键的一点来了,我们的子类感觉到了变化吗?

没有,实现的子类的代码没有修改。

也就说这样代码就写活了。

针对借口编程,而不是针对实现编程。

而需要不同的吃的行为只要传进去不同的eat的接口的实现类就好了。

多用组合,少用继承。

好了,这就是策略模式。

定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: