我眼中的策略模式_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 我眼中的策略模式

我眼中的策略模式

 2011/11/29 10:14:29  梵_心  http://fan-xin.iteye.com  我要评论(0)
  • 摘要:前一段时间在朋友的极力推荐下,有幸拜读了head.first的大作《设计模式》,阅读了几章之后猛然发现,原来技术文章也可以写的如此通俗,优雅。遂想将个人的一些读后感和对书中设计模式的理解整理成文,与众程序员朋友分享。同时,也希望您能慷慨的发表自己的看法与理解,帮助新晋的程序员朋友在软件开发之路上走的更加从容。如果您正好看过此书,请一定不吝赐教。欢迎大家拍砖!下面是我对书中策略模式的讲解的分析:场景:一款模拟鸭子的游戏,游戏中出现各种鸭子,一边戏水,一边呱呱叫描述:有一个鸭子的抽象类
  • 标签:模式
        前一段时间在朋友的极力推荐下,有幸拜读了head.first 的大作《设计模式》,阅读了几章之后猛然发现,原来技术文章也可以写的如此通俗,优雅。遂想将个人的一些读后感和对书中设计模式的理解整理成文,与众程序员朋友分享。同时,也希望您能慷慨的发表自己的看法与理解,帮助新晋的程序员朋友在软件开发之路上走的更加从容。如果您正好看过此书,请一定不吝赐教。欢迎大家拍砖!

下面是我对书中策略模式的讲解的分析:


场景:一款模拟鸭子的游戏,游戏中出现各种鸭子,一边戏水,一边呱呱叫
描述:有一个鸭子的抽象类,各种鸭子继承此类
鸭子种类:红头鸭,绿头鸭,木头假鸭,橡皮鸭
抽象类的方法:quack(),swim(),abstract display()
补充:抽象类中已对quack和swim进行了实现。鸭子正常叫为呱呱叫,红头与绿头鸭呱呱叫,木头鸭不会叫,橡皮鸭会吱吱叫
此设计优点:子类可复用quack(),swim()方法
此设计缺点:个别种类的鸭子需要覆盖父类的quack方法满足自己的需求(例如木头鸭不会叫)

public abstract class Duck{
  public void quack(){
     System.out.println("呱呱叫");
  }

  public void swim(){
     System.out.println("戏水");
  }

  public abstract void display();
}



需求:需要某些鸭子能够飞行

方案一:在超类中增加fly()方法并对其实现
缺点:所有的鸭子都拥有了fly()的功能,哪怕本身不能fly(),凡是增加新的鸭子类都需要对fly()方法进行检测,如不需要则必须覆盖

public abstract class Duck{
  public void quack(){
     System.out.println("呱呱叫");
  }

  public void swim(){
     System.out.println("戏水");
  }

  public void fly(){
     System.out.println("飞行");
  }
  
  public abstract void display();
}


方案二:将fly()方法抽出写入接口,需要的自行实现该接口
缺点:无法复用,重复代码增多

public interface Flyable{
  public void fly();
}



症结:鸭子的某些行为在子类中会不断的变化,让所有子类都拥有这类的行为是不恰当的


设计原则:(封装变化)找出应用中可能需要变化之处,把它们独立出来,和不需要改变的分开,以便它们可以独立的修改和扩展而不影响其他部分

解答:将fly,quack方法抽出为两组独立的类型,并根据需要进行不同的实现。例如,quack类型组可以包含,安静,呱呱叫,吱吱叫

public interface Quack{
  public void quack();
}

public interface Flyable{
  public void fly();
}

public class FlyWithWing implements Flyable{
  public void fly(){
     System.out.println("用翅膀飞行");
  }
}

public class ZhiZhiQuack implements Quack{
  public void quack(){
     System.out.println("吱吱叫");
  }
}

public class GuaGuaQuack implements Quack{
  public void quack(){
     System.out.println("呱呱叫");
  }
}



补充:由于一开始鸭子行为设计的没有弹性才出现了以上的情况,所以应该采用一种弹性的方案。可以根据需要动态改变鸭子的行为


设计原则:(鸭子类不在拥有具体的行为实现方法,只拥有行为的引用接口)针对接口编程,而不是针对实现编程

解答:鸭子的行为放在分开的类中,让该类提供某行为接口的实现


设计原则:多用组合,少用继承(鸭子的行为不再是继承而来,而是组合而来)


设计模式:策略模式,定义了算法族(鸭子的行为类型组),分别封装起来,让他们之间可以相互替换,此模式让算法的变化(鸭子的行为)独立于使用算法的客户(鸭子)

public abstract class Duck{
  private Quack quack;
  private Flyable fly;

  public void executeQuack(){
      quack.quack();
  }

  public void executeFly(){
      fly.fly();
  }

  public void setQuack(Quack q){
      this.quack=q;
  }

  public void setFly(Flyable f){
      this.fly=f;
  }

  public void swim(){
     System.out.println("戏水");
  }

  public abstract void display();
}

子类在构造时设定具体的行为即可,并且在运行时也可动态改变。

下面是我对此模式中所使用的一些软件设计原则的看法与感悟:

封装变化:
1.为每种行为的变化定义接口
2.将每种具体的行为封装为类并实现该种行为的接口
解释:本例中的变化的类型是鸭子的行为,包含fly,quack两组。分别对其定义接口,再根据具体的需求予以实现。例如quack接口包含(呱呱叫,吱吱叫,无声)三种具体的实现

针对接口编程:
1.将具体实现委托给接口
2.问题域类只负责接口级别的逻辑控制
3.问题域类的责任依赖于持有的抽象接口而不是具体实现
解释:鸭子类只持有行为的接口,本身不负责实现。对鸭子类进行了细粒度的抽象,将其具体的行为予以抽离,该问题域类(鸭子)的责任只依赖于内部所持有的接口

多用组合,少用继承:
1.通过组合的方式构建类的行为,而不是继承。可以使类更加灵活,在运行期可动态改变行为


以上便是我的理解,如有不对或者疑惑之处欢迎指出!文中只写出主要的代码,其他代码均已省略,若有需要的朋友可自行参阅该书,亦可发站内信向我索取!


发表评论
用户名: 匿名