设计模式解读之:策略模式
作者:网络转载 发布时间:[ 2013/8/7 11:04:16 ] 推荐标签:
通过以上设计,fly()行为以及quack()行为已经和Duck.java没有什么关系,可以充分得到复用。而且我们很容易增加新的行为,既不影响现有的行为,也不影响Duck.java。但是,大家可能有个疑问,是在面向对象中行为不是体现为方法吗?为什么现在被定义形成类(例如Squeak.java)?在OO中,类代表的"东西"一般是既有状态(实例变量)又有方法。只是在本例中碰巧"东西"是个行为。既使是行为,也有属性及方法,例如飞行行为,也需要一些属性记录飞行的状态,如飞行高度、速度等。
2)整合变化的内容和不变的内容
Duck.java将fly()以及quack()的行为委托给行为类处理。
不变的内容:
publicabstractclassDuck{
//将行为类声明为接口类型,降低对行为实现类型的依赖
FlyBehaviorflyBehavior;
QuackBehaviorquackBehavior;
publicvoidperformFly(){
//不自行处理fly()行为,而是委拖给引用flyBehavior所指向的行为对象
flyBehavior.fly();
}
publicvoidperformQuack(){
quackBehavior.quack();
}
publicvoidswim(){
System.out.println("Allducksfloat,evendecoys.");
}
publicabstractvoiddisplay();
}
Duck.java不关心如何进行fly()以及quack(),这些细节交由具体的行为类完成。
publicclassMallardDuckextendsDuck{
publicMallardDuck(){
flyBehavior=newFlyWithWings();
quackBehavior=newQuack();
}
publicvoiddisplay(){
System.out.println("Greenhead.");
}
}
测试类:
publicclassDuckTest{
publicstaticvoidmain(String[]args){
Duckduck=newMallardDuck();
duck.performFly();
duck.performQuack();
}
}
在Duck.java子类型MallardDuck.java的构造方法中,直接实例化行为类型,在编译的时侯便指定具体行为类型。当然,我们可以:
1)我们可以通过工厂模式或其它模式进一步解藕(可参考后续模式讲解);
2)或做到在运行时动态地改变行为。
3)动态设定行为
在父类Duck.java中增加设定行为类型的setter方法,接受行为类型对象的参数传入。为了降藕,行为参数被声明为接口类型。这样,既便在运行时,也可以通过调用这二个方法以改变行为。
publicabstractclassDuck{
//在刚才Duck.java中加入以下二个方法。
publicvoidsetFlyBehavior(FlyBehaviorflyBehavior){
this.flyBehavior=flyBehavior;
}
publicvoidsetQuackBehavior(QuackBehaviorquackBehavior){
this.quackBehavior=quackBehavior;
}
//其它方法同,省略...
}
测试类:
publicclassDuckTest{
publicstaticvoidmain(String[]args){
Duckduck=newMallardDuck();
duck.performFly();
duck.performQuack();
duck.setFlyBehavior(newFlyNoWay());
duck.performFly();
}
}
如果,我们要加上火箭助力的飞行行为,只需再新建FlyBehavior.java接口的实现类型。而子类型可通过调用setQuackBehavior(...)方法动态改变。至此,在Duck.java增加新的行为给我们代码所带来的困绕已不复存在。
该是总结的时侯了,让我们从代码的水中浮出来,做一只在水面上自由游动的鸭子吧:
3.解决方案
MallardDuck继承Duck抽象类;->不变的内容
FlyWithWings实现FlyBehavior接口;->变化的内容,行为或算法
在Duck.java提供setter方法以装配关系;->动态设定行为
以上是策略模式的实现三步曲。接下来,让我们透过步骤看本质:
1)初始,我们通过继承实现行为的重用,导致了代码的维护问题。->继承,isa
2)接着,我们将行为剥离成单独的类型并声明为不变内容的实例变量并通过->组合,hasa
setter方法以装配关系;
继承,可以实现静态代码的复用;组合,可以实现代码的弹性维护;使用组合代替继承,可以使代码更好地适应软件开发完后的需求变化。
策略模式的本质:少用继承,多用组合。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11