23中设计模式之策略模式

来源:互联网 发布:惠普q1910更新软件 编辑:程序博客网 时间:2024/06/09 15:26

策略模式

       提起强大的Java,脑海里总会蹦出几个关键字,封装,继承,多态,一处编译处处运行,代码复用等等,而设计模式在我的学习中认为是前人经验的复用,从而让Java写出来的系统更加的具有延展性,以应变后面需求的变化.今天要学习的就是策略模式.

 

       有一个国家人员复杂,管理起来麻烦,此时他历经千辛万苦找到了你,在随从的侍卫放下两大箱的黄金之后,请求你为国家设计一个人员管理系统,但在此之前他需要考量一下你, 假设有如此需求,这是一个尚武的国家,有剑客,弓箭手,战士(使用斧头)等,此时需要你写一个小的demo来管理各自人员的战斗方式.

       为了尽早拿下这个项目,于是咖啡都没有冲,你就自信的选择了继承来实现;

       1,首先定义抽象父类,将fight()的方式留给子类来实现

       父类Role

publicabstractclass Role {

       protected Stringname;

       protected Integerage;

      

       protectedvoid breath(){

              System.out.println("我们都呼吸空气");

       }

      

       protectedabstractvoid fight();

}

       子类1,弓箭手

       publicclass BowMan extends Role{

 

       @Override

       protectedvoid fight() {

              System.out.println("我是弓箭手,我的武器是弓箭!");

       }

 

}

       子类2,剑客

publicclass SwordMan extends Role{

 

       @Override

       protectedvoid fight() {

              System.out.println("我是剑客,我的武器是剑!");

       }

 

}

       子类3,战士

public class WarriorMan extendsRole{

 

       @Override

       protectedvoid fight() {

              System.out.println("我是战士,我的武器是斧头!");

       }

 

}

       定义测试类:

public class RoleTest {

 

       @Test

       publicvoid test4RoleExtends(){

              Role role1 = new BowMan();

              Role role2 = new SwordMan();

              Role role3 = new WarriorMan();

              role1.breath();

              role2.breath();

              role3.breath();

              role1.fight();

              role2.fight();

              role3.fight();

       }

}

       测试结果:控制台输出如下:

我们都呼吸空气

我们都呼吸空气

我们都呼吸空气

我是弓箭手,我的武器是弓箭!

我是剑客,我的武器是剑!

我是战士,我的武器是斧头!

我要参加战斗!

我要参加战斗!

我要参加战斗!

你向国外许诺,这个系统足以应付所有的问题,无论来什么样的角色,它都可以完美应对,国王很快将他推向了全民,并且Role的子类越来越多,这个系统完美地运行着,有一天国王突发奇想,没错就是突发奇想,需要选拔一些远攻role去攻克一个难关,国王希望国家里的人来报名,深感Java继承的巨大优势的你嗅到了升官发财三妻四妾的契机,大包大揽的应承了这份工作,悠闲的冲了杯咖啡,修改了Role类

publicabstractclass Role {

       protected Stringname;

       protected Integerage;

      

       protectedvoid breath(){

              System.out.println("我们都呼吸空气");

       }

      

       protectedabstractvoid fight();

       //报名参加战斗

       protectedvoid regiesterFight() {

              System.out.println("我要参加战斗!");

       }

}

       选拔开始:

       publicclass RoleTest {

 

       @Test

       publicvoid test4RoleExtends(){

              Role role1 = new BowMan();

              Role role2 = new SwordMan();

              Role role3 = new WarriorMan();

              role1.breath();

              role2.breath();

              role3.breath();

              role1.fight();

              role2.fight();

              role3.fight();

              role1.regiesterFight();

              role2.regiesterFight();

              role3.regiesterFight();

       }

}

全民响应战斗:

 

于是乎,战场上一群扔了斧头和剑就没法再战斗的role,因为这场战斗需要远程投掷.毫无疑问,这场战斗,大败而归,国王大怒,责令你一周之内拿出解决方案,否则剥夺你喝咖啡的权利,没有了咖啡,你就很有可能在代码的海洋中溺死.

       此时你想起了尘封了很久的武林秘籍,headfirst之设计模式,哪一个模式才能应付这样行为多变的情况呢,思考了六天,在毫无头绪中度过,第七天终于想起了那根救命稻草---策略模式.

       策略模式:

              定义算法族,让算法和使用算法的用户分离起来.

将战斗和报名战斗的行为委托出去分别由FightBehavior和RegFightBehavior两个接口(面向接口编程,远远胜于面向实现编程),行为的具体方式由其不同的实现类实现.

重新定义Role

publicabstractclass Role {

       protected Stringname;

       protected Integerage;

       protected FightBehavior fightBehavior;

       protected RegFightBehavior regFightBehavior;

       protectedvoid breath(){

              System.out.println("我们都呼吸空气");

       }     

}

定义接口FightBehavior,RegFightBehavior

public interface FightBehavior {

       publicvoid fight();

}

其实现类:

public class FightByAxe implementsFightBehavior{

 

       @Override

       publicvoid fight() {

              System.out.println("我用斧头!!!");

       }

 

}

 

public class FightByBow implementsFightBehavior{

 

       @Override

       publicvoid fight() {

              System.out.println("我用弓箭!!!");

       }

 

}

 

public class FightBySword implementsFightBehavior{

 

       @Override

       publicvoid fight() {

              System.out.println("我用剑!!!");

       }

 

}

将战斗的行为分离出来,并叫交由其实现类来处理,在role中添加战斗行为属性,而不需要考虑其如何实现的.

public interface RegFightBehavior {

       publicvoid regFight();

}

 

public class RegFightByClose implements RegFightBehavior{

 

       @Override

       publicvoid regFight() {

              System.out.println("我是近战,我不能参加!!");

       }

      

}

 

public class RegFightByFar implements RegFightBehavior{

 

       @Override

       publicvoid regFight() {

              System.out.println("我是远攻我要参加");

       }

      

}

 

是否参加战斗这一行为也是如此,为了形象的表现将行为委托出去了,将命名变为byFar byClose这种方式.

此时再在role的子类中,定义或者赋予行为类的具体委托类,也就是指定客户使用的算法

publicclass BowMan extends Role{

      

       publicvoidfight(){

              fightBehavior =newFightByBow();

              fightBehavior.fight();

       }

       publicvoidregFight(){

              regFightBehavior =newRegFightByFar();

              regFightBehavior.regFight();

       }

}

 

publicclass SwordMan extends Role{

 

       publicvoidfight() {

              fightBehavior =newFightBySword();

              fightBehavior.fight();

       }

       publicvoidregFight(){

              regFightBehavior =newRegFightByClose();

              regFightBehavior.regFight();

       }

}

 

public class WarriorMan extendsRole{

 

       publicvoid fight() {

              fightBehavior= new FightByAxe();

              fightBehavior.fight();

       }

 

       publicvoid regFight(){

              regFightBehavior= new RegFightByClose();

              regFightBehavior.regFight();

       }

}

 

测试类

public class RoleTest {

 

       @Test

       public voidtest4RoleExtends(){

              Rolerole1 = new BowMan();

              Rolerole2 = new SwordMan();

              Rolerole3 = new WarriorMan();

              role1.fight();

              role1.regFight();

              System.out.println("以上是bowman");

              role2.fight();

              role2.regFight();

              System.out.println("以上是swordman");

              role3.fight();

              role3.regFight();

              System.out.println("以上是warriorman");

       }

}

测试结果:

我用弓箭!!!

我是远攻我要参加

以上是bowman

我用剑!!!

我是近战,我不能参加!!

以上是swordman

我用斧头!!!

我是近战,我不能参加!!

以上是warriorman