策略模式
定义
什么是策略模式?定义了算法族,分别封装起来,让它们之间能够互相替换,此模式让算法的变化独立于使用算法的客户。
个人理解就是:好比咱们接下来要说到的鸭子案例,有的鸭子能够飞,而飞又分为不少种,飞很高,飞得很低各类,咱们就会把飞这个行为定义为接口,而后再分别去实现,而咱们的鸭子只须要注入“飞”的行为,就能够去飞,至于怎么飞,鸭子不用去管,这也算是面向接口编程吧。固然除了飞,还有不少行为,咱们均可以把这些行为抽成接口,而后再具体实现,让鸭子有接口类型的变量,就有了对应的行为啦~固然鸭子也分不少种,好比橡皮泥鸭子,这是确定不能飞行的,那么咱们就不须要去给他设置飞行实现就行了。很是的灵活,能够面对各类变化, 好比鸭子受伤了,不能飞了,那就修改下鸭子注入的飞行行为的实现,再好比鸭子又多了一种技能,能呱呱叫了,那就再写一个呱呱叫接口,至于怎么呱呱叫,让具体的实现去解决。html
接下来我来粘贴一下《Head First 设计模式》上的案例即鸭子算法
举例
首先是鸭子抽象类:编程
我定义了一个FlyBehavior类型的变量,这个FlyBehavior是一个飞行行为的接口,这就意味着鸭子有了飞行行为设计模式
至于怎么飞,咱们不须要考虑,交给飞行的实现去飞,也就是performFly(),同时还有一个setFlyBehavior(),这个方法就意味着,鸭子可以在运行时动态的修改本身飞行的实现,好比原本是“飞的很高”,后来鸭子年纪大了,飞不了很高了,那就用这个方法修改一下本身的飞行实现。好比duck.setFlyBehavior(new FlyLow()); app
package object; import behaviour.FlyBehavior; public abstract class Duck { protected FlyBehavior flyBehavior; public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public abstract void swim(); public abstract void display(); public void performFly(){ flyBehavior.fly(); } }
有了抽象类确定要有实现类呀,这就奉上香喷喷的"驯化野鸭”ide
flyBehavior的变量是从父类Duck继承过来的,而FlyWithWings是实现了FlyBehavior接口的"用翅膀飞行”,MallardDuck的构造函数就意味着,"驯化野鸭"对飞行行为的描述默认是“用翅膀飞行”,固然若是想改变它的飞行行为,那么只须要用刚刚提到的父类中的setFlyBehavior()方法就行了。函数
package object.concreteobject; import behaviour.FlyWithWings; import object.Duck; public class MallardDuck extends Duck{ public MallardDuck(){ flyBehavior = new FlyWithWings(); } @Override public void swim() { // TODO Auto-generated method stub System.out.println("I'm swimming!"); } @Override public void display() { System.out.println("I'm a real Mallard duck"); } }
固然,既然是粘贴代码,就必定要粘贴全,这就附上FlyBehavior接口和两个实现类,为了方便我就放在一块儿了。学习
package behaviour; public interface FlyBehavior { void fly(); } package behaviour; public class FlyWithWings implements FlyBehavior{ @Override public void fly() { System.out.println("flywithwings"); } } package behaviour; public class FlyNoWay implements FlyBehavior { @Override public void fly() { System.out.println("I can't fly"); } }
接下来咱们就能够测试这只“驯化野鸭”的飞行行为了。测试
测试当中呢,首先先飞行了一下,固然会展现“驯化野鸭”的默认飞行行为,即“flywithwings”,随后小鸭子不当心受伤了它暂时不能飞行了,咱们给它动态地从新设置了飞行行为,最后伤好了,天然又能够飞行了,而后只须要再从新设置就行了~this
package test; import behaviour.FlyNoWay; import behaviour.FlyWithWings; import object.Duck; import object.concreteobject.MallardDuck; public class Test { public static void main(String[] args) { Duck mallard = new MallardDuck(); mallard.performFly(); System.out.println("------------------------------"); System.out.println("我不当心受伤了,这段时间我不能飞行了。。。"); System.out.println("------------------------------"); mallard.setFlyBehavior(new FlyNoWay()); mallard.performFly(); System.out.println("------------------------------"); System.out.println("我有恢复健康了~"); System.out.println("------------------------------"); mallard.setFlyBehavior(new FlyWithWings()); mallard.performFly(); } }
看,说的没错吧。。。。
这基本就是我对策略模式的学习总结吧,这个案例也是《Head First设计模式》中的,鸭子(各类鸭子), 各类行为(行为1[具体的行为1,具体的行为2.......],行为2[具体的行为1,具体的行为2.......] .......),鸭子有不少种类,有的特殊的鸭子确定有特殊行为,而行为可能一时也很差总结,谁知道哪天又会横空出世一种行为呢? 鸭子能够经过策略模式,动态地绑定行为,而新增行为,只须要再写个接口,随后再Duck类中加上对应的类型的变量就行了。(我仍是再写一下吧,看看本身是否是真的理解了。。)
举例
原本想继续扩展鸭子,可是看到书上有另外一案例。。
接下来就是粘贴代码了,粗略的写了一下,大概情节就是,角色: 有公主和骑士...,有两种行为,使用武器,跳舞,默认公主不会跳舞,和用匕首刺杀,而骑士能够用宝剑刺杀,没有跳舞行为。随后公主学了跳舞,变有了快乐地跳起了舞~
两种行为:
package behaviour; /** * 跳舞 * * @author DeepSleeping * */ public interface DanceBehavior { void dance(); } package behaviour; /** * 可使用武器 * @author DeepSleeping * */ public interface WeaponBehavior { void useWeapon(); }
两种行为对应的具体实现(表现):
package behaviour; /** * 快乐地跳舞 * * @author DeepSleeping * */ public class DanceHappy implements DanceBehavior { @Override public void dance() { System.out.println("快乐地跳舞!"); } } package behaviour; /** * 不可能跳舞 * * @author DeepSleeping * */ public class DanceNoWay implements DanceBehavior { @Override public void dance() { System.out.println("我怎么可能会跳舞!"); } } package behaviour; /** * 使用匕首 * * @author DeepSleeping * */ public class KnifeBehavior implements WeaponBehavior { @Override public void useWeapon() { System.out.println("-使用匕首刺杀-"); } } package behaviour; /** * 使用宝剑 * * @author DeepSleeping * */ public class SwordBehavior implements WeaponBehavior { @Override public void useWeapon() { System.out.println("-使用宝剑刺杀-"); } }
角色,以及角色下的 公主、骑士
package object; import behaviour.DanceBehavior; import behaviour.WeaponBehavior; /** * 角色 * * @author DeepSleeping * */ public abstract class Character { WeaponBehavior wb; DanceBehavior db; public void setDb(DanceBehavior db) { this.db = db; } public void setWb(WeaponBehavior wb) { this.wb = wb; } /** *战斗 */ public void fight() { wb.useWeapon(); } /** * 跳舞 */ public void dance() { db.dance(); } } package object; import behaviour.DanceNoWay; import behaviour.SwordBehavior; /** * 骑士 * * @author DeepSleeping * */ public class Knight extends Character { public Knight() { // 默认骑士是用宝剑的 wb = new SwordBehavior(); } } package object; import behaviour.DanceNoWay; import behaviour.KnifeBehavior; /** * 公主 * @author DeepSleeping * */ public class Queen extends Character{ public Queen(){ //默认公主是用匕首的 wb = new KnifeBehavior(); //默认公主不会跳舞 db = new DanceNoWay(); } }
开始测试~
package test; import behaviour.DanceHappy; import behaviour.SwordBehavior; import object.Character; import object.Knight; import object.Queen; public class Test { public static void main(String[] args) { Character knight = new Knight(); Character queen = new Queen(); // 骑士去刺杀 knight.fight(); // 公主去刺杀 queen.fight(); // 公主换成用宝剑刺杀 queen.setWb(new SwordBehavior()); queen.fight(); System.out.println("--------------------"); queen.dance(); // 公主学会了跳舞 queen.setDb(new DanceHappy()); queen.dance(); } }
总结
总结下几个不错的设计原则:
1.找出应用中可能须要变化之处,把它们独立出来,不要和那些不须要变化的代码混在一块儿。
2.针对接口编程,而不是针对实现编程。
3.多用组合,少用继承
好了 ,策略模式就认识到这了,经过学习,我也算是对策略模式有了初步的认识吧,中间写着写着感受好像装饰者模式啊,哈哈,又有点蒙了,继续学习吧。。。
参考材料:《Head First设计模式》
原文出处:https://www.cnblogs.com/deepSleeping/p/10738020.html