设计模式学习之——策略模式
2016-07-17 19:21
429 查看
使用设计模式最好的方式:把设计模式装进脑袋里面,然后在你的设计和已有的应用中,寻找何处可以使用它们。
设计模式是一种前人踩过的坑,之后总结下来的编程经验,也就是说这样做通常比较好。我们学习这种经验,以便在我们以后的项目中避免很多问题。
原来有一些行为,现在要加入飞行的方法。那么怎么做才是最好的解决方法呢?
注意,并不是所有的鸭子都能飞。
所以直接在父类里面加进去飞行方法是有问题的。
这个飞行动作 是可变的,并不是每种都有的。
涉及到维护的时候,为了复用而使用继承,结局并不好。
对超类进行局部修改,影响层面是全局的。
如果使用接口,那么虽然解决了只有会飞的鸭子才能飞的问题,但是呢,却造成了原来所有的实现都要修改和大量的代码冗余。
解决办法
每次新的需求来了,需要改变的部分,就是要封装起来的部分。
核心思想:把会变化的部分取出并封装起来 ,以便以后可以轻易地改动或者扩展此部分,而不影响其他不需要变化的部分。
把飞行的行为作为一个借口,依附于超级鸭子父类
鸭子的子类使用接口所表示的行为,不会绑死在鸭子的子类里面。
下面是全部代码
首先是 duck类
}
接下来是飞行接口。
}
实现飞行借口的类
}
另一个
}
最后我们真正用到的鸭子
}
测试类
运行结果
翅膀飞
我不会飞!
}
那么假如要加入一个新的行为,比如说eat ,这个行为至少橡皮鸭子就是不能吃的。
所以首先要新写一个eat的接口。
}
实现接口的具体吃法
}
接下来修改原来的DUCK类
}
测试类
public class TestEat {
}
这样就可以动态的改变新的属性了。
那么最关键的一点来了,我们的子类感觉到了变化吗?
没有,实现的子类的代码没有修改。
也就说这样代码就写活了。
针对借口编程,而不是针对实现编程。
而需要不同的吃的行为只要传进去不同的eat的接口的实现类就好了。
多用组合,少用继承。
好了,这就是策略模式。
定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
设计模式是一种前人踩过的坑,之后总结下来的编程经验,也就是说这样做通常比较好。我们学习这种经验,以便在我们以后的项目中避免很多问题。
应用场景
举个例子,一个鸭子类。原来有一些行为,现在要加入飞行的方法。那么怎么做才是最好的解决方法呢?
注意,并不是所有的鸭子都能飞。
所以直接在父类里面加进去飞行方法是有问题的。
这个飞行动作 是可变的,并不是每种都有的。
涉及到维护的时候,为了复用而使用继承,结局并不好。
对超类进行局部修改,影响层面是全局的。
如果使用接口,那么虽然解决了只有会飞的鸭子才能飞的问题,但是呢,却造成了原来所有的实现都要修改和大量的代码冗余。
解决办法
每次新的需求来了,需要改变的部分,就是要封装起来的部分。
核心思想:把会变化的部分取出并封装起来 ,以便以后可以轻易地改动或者扩展此部分,而不影响其他不需要变化的部分。
把飞行的行为作为一个借口,依附于超级鸭子父类
鸭子的子类使用接口所表示的行为,不会绑死在鸭子的子类里面。
下面是全部代码
首先是 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的接口的实现类就好了。
多用组合,少用继承。
好了,这就是策略模式。
定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
相关文章推荐
- POJ 1087 A Plug for UNIX(最大流)
- Linux如何查看用户组及用户信息
- slidingMenuFragment
- deploy type选哪个,J2EE项目以“Exploded Archive”模式部署时无效
- 静态网页的大体框架
- 马哥培训
- Android 在不同Actitity之间数据传递
- JAVA获取文件的几种常用方式
- 没看出来
- cholesky分解的实现
- 【链表】C++两个链表的公共结点
- 循环结构一(while,do while)
- Spring IOC 注解annotation的几种方式
- 安装CentOS Core之后布置环境脚本
- java基本类型数组初始化
- TSP问题的模拟退火解法
- 两个和标算擦肩而过。
- ListView的Adapter在getView()的时候position始终为0,异常解决了,求解答根本原因
- jsp bootstrap表单页面
- 方法重载和重写的详细总结