模式的秘密——策略模式

模式的秘密——策略模式

一、   什么是策略模式

策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

 

二、   实例说明

例一

设计一个书籍电子商务网站的购物车系统,最简单的情况就是把所有商品的单价乘上数量,但是实际情况比这要复杂。比如,系统可能对高级会员提供每本书20%的折扣;对中级会员提供每本书10%的折扣;对初级会员没有折扣。

根据描述,实付金额是根据以下几个策略进行计算的:

策略一:初级会员没有折扣

策略二:中级会员提供10%的折扣

策略三:高级会员提供20%的折扣


源码实现:

1、       会员折扣的抽象类MemberStrategy.java

public interfaceMemberStrategy {

   /*

    * 计算图书的价格

    *

    * @param booksPrice 图书的原价

    *

    * @return 计算出打折后的价格

    */

   public doublecalcPrice(double booksPrice);

}

2、       初级会员折扣策略PrimaryMemberStrategy.java

public classPrimaryMemberStrategy implementsMemberStrategy{

   public PrimaryMemberStrategy() {

      // TODO Auto-generated constructor stub

   }

   @Override

   public doublecalcPrice(double booksPrice) {

      // TODO Auto-generated method stub

      System.out.println("初级会员不享受折扣");

      return booksPrice;

   }

}

3、       中级会员的折扣策略InterMediateMemberStrategy.java

public classInterMediateMemberStrategy implementsMemberStrategy {

   public InterMediateMemberStrategy() {

      // TODO Auto-generated constructor stub

   }

 

   @Override

   public doublecalcPrice(double booksPrice) {

      // TODO Auto-generated method stub

      System.out.println("中级会员享受10%的折扣");

      return booksPrice * 0.9;

   }

}

4、       高级会员的折扣策略AdvancedMemberStrategy.java

public classAdvancedMemberStrategy implementsMemberStrategy {

 

   public AdvancedMemberStrategy() {

      // TODO Auto-generated constructor stub

   }

 

   @Override

   public doublecalcPrice(double booksPrice) {

      // TODO Auto-generated method stub

      System.out.println("高级会员享受20%的折扣");

      return booksPrice * 0.8;

   }

 

}

5、       价格计算类Price.java

public class Price {

   // 一个具体的策略对象

   private MemberStrategy strategy;

 

   public Price(MemberStrategy strategy) {

      this.strategy = strategy;

   }

 

   /*

    * 计算图书的价格

    */

   public double quote(double booksPrice) {

      return this.strategy.calcPrice(booksPrice);

   }

 

}

6、       客户端

public class Client {

 

   public static void main(String[] args) {

      // 选择并创建需要使用的策略对象

      MemberStrategystrategy = null;

//    strategy= new PrimaryMemberStrategy();

//    strategy = new InterMediateMemberStrategy();

       strategy = new AdvancedMemberStrategy();

      Priceprice = new Price(strategy);

      double quote = price.quote(300);

      System.out.println("图书的实际价格为:" + quote);

   }

 

}

运行截图:




由此我们可以看出,策略模式仅仅封装对问题的不同处理方式和不同的算法,提供新的算法插入到也有系统中,以及老算法从系统中“退休”的方法,策略模式并不决定何时使用何种算法。在什么情况下使用什么算法由客户端决定。

 

例二

       这个例子来自慕课网关于策略模式的教学视频,讲的是关于鸭子能不能飞的问题。

1、       鸭子的抽象类Duck.java

public abstract class Duck {

   /*

    * 鸭子发出叫声通用行为,由超类实现

    */

   public void quack() {

      System.out.println("嘎嘎嘎");

   }

 

   /*

    * 显示鸭子的外观鸭子的外观各不相同,声明为abstract,由子类实现

    */

   public abstract void display();

 

   private FlyingStrategy flyingStrategy;

 

   public FlyingStrategy getFlyingStrategy() {

      return flyingStrategy;

   }

 

   public voidsetFlyingStrategy(FlyingStrategy flyingStrategy) {

      this.flyingStrategy = flyingStrategy;

   }

  

   public void fly(){

      flyingStrategy.performFly();

   }

}

2、       鸭子的飞行策略接口FlyingStrategy.java

/*

 * 策略接口,实现鸭子的飞行行为

 */

public interfaceFlyingStrategy {

   void performFly();

}

3、       不能飞行的策略FlyNoWay.java

public class FlyNoWay implements FlyingStrategy {

 

   @Override

   public void performFly() {

      // TODO Auto-generated method stub

      System.out.println("我不会飞行");

   }

 

}

4、       使用翅膀飞行策略FlyWithWin.java

public class FlyWithWin implements FlyingStrategy {

 

   @Override

   public void performFly() {

      // TODO Auto-generated method stub

      System.out.println("振翅高飞");

   }

 

}

5、       活物红头鸭RedHeadDuck.java

public class RedheadDuck extends Duck {

   public RedheadDuck() {

      super();

      super.setFlyingStrategy(new FlyWithWin());

      // TODO Auto-generated constructor stub

   }

 

   @Override

   public void display() {

      // TODO Auto-generated method stub

      System.out.println("我的头是红色的");

   }

 

}

6、       玩具塑料鸭RubberDuck.java

public class RubberDuck extends Duck {

 

   public RubberDuck() {

      // TODO Auto-generated constructor stub

      super();

      super.setFlyingStrategy(new FlyNoWay());

   }

   @Override

   public void display() {

      // TODO Auto-generated method stub

      System.out.println("我是塑料做的");

 

   }

   @Override

   public void quack() {

      // TODO Auto-generated method stub

      System.out.println("~~~");

   }

 

}

7、       测试

public class DuckTest {

 

   public static void main(String[] args) {

      // TODO Auto-generated method stub

      System.out.println("测试鸭子的程序");

      Duckduck = null;

//    duck= new RedheadDuck();

      duck = new RubberDuck();

     

      duck.display();

      duck.quack();

      duck.fly();

 

      System.out.println("测试完毕");

   }

 

}

8、       运行结果



       我们在实现鸭子飞行的时候可以很容易想到的方法如下:

方法一:继承

       在父类中提供一个实现方法,子类通过继承获得父类中的飞行行为。这种方法充分地利用了面向对象的思想,简单总结一下这种方式的优缺点。

优点:简单易用,已有应用可以快速添加飞行的能力

缺点:不具有灵活性,对未来变更支持差。需要通过在子类中覆写飞行的方法以提供飞行的行为。这很容易造成错误(粗心的程序员容易忘记覆写)。

 

方法二:抽象方法

       在父类中提供抽象方法,强迫子类实现自己的飞行行为。这种方法的优缺点如下。

优点:足够灵活,小伙伴再也不用担心忘记覆写代码了。

缺点:工作量大,每个子类都要实现一遍代码,即使是相同的行为也不例外。

 

三、   策略模式的优点

1、          使用了组合,使架构更加灵活

2、          富有弹性,可以较好的应对变化(开——闭原则)

3、          更好的代码复用性(相对于继承)

4、          消除大量的条件语句

              

四、   策略模式的缺点

1、       客户代码需要了解每个策略实现的细节

2、       增加了对象的数目

 

五、   适用场景

1、       许多相关的类仅仅是行为差异

2、       运行时选取不同的算法变体

3、       通过条件语句在多个分支中选取一个

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值