前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >策略模式浅析

策略模式浅析

作者头像
孟君
发布2019-10-10 10:50:02
4380
发布2019-10-10 10:50:02
举报

在开始本文之前,我们先来看下生活中的的一些场景:

  • 场景1:出行

比如出行,可以采用公共汽车出行,可以打的出行,可以自驾出行,也可以骑自行车出行等等。我们可以根据天气、距离、时间紧迫等因素决定采用哪一种方式出行。

场景2:购物车支付

比如购物支付,可以采用信用卡、银联、支付宝、微信等方式支付,每种都有各自的算法和行为。

再如采用不同策略完成计费、完成排序等都是在多个现实应用可以找到的。在这些场景中,将算法封装在对象中,这样可以方便地指定和改变一个对象所使用的算法。这个就是我们要聊的策略模式要做的事情。

一、策略模式的基本介绍

1.1 意图

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换策略模式使得算法可独立于使用它的客户而变化

1.2 结构

策略模式的基本结构如下:

  • Strategy (策略)
    • 定义所有支持的算法的公共接口,通常由一个接口或抽象类实现。
  • ConcreteStrategy (具体策略)
    • 以Strategy接口实现某具体算法。
  • Context (上下文)
    • 持有一个对Strategy对象的引用

二、策略模式的示例

本文给出一个发短信的示例,平台需要根据不同的省份和场景,通过不同的网关发送短信。

发送短信的方式有如下几种方式:

  • 通过自主平台短信网关发送短信
  • 通过省级短信网关发送短信
  • 通过信息调度中心10086发送短信 接下来,根据策略模式的结构完成一个简单的示例:
  • MessageStrategy (Strategy)
package com.wangmengjun.tutorial.designpattern.strategy;

public interface MessageStrategy {

    void sendMessage(String message, String phone);
  
}
  • 三个具体策略(ConcreteStrategy)
  • HySmsStrategy.java
package com.wangmengjun.tutorial.designpattern.strategy;

public class HySmsStrategy implements MessageStrategy{

  @Override
  public void sendMessage(String message, String phone) {
    System.out.println(String.format("通过自主平台短信网关发送短信,message=[%s],"
        + "phone=[%s]", message, phone));
  }

}
  • CustomerSmsStrategy.java
package com.wangmengjun.tutorial.designpattern.strategy;

public class CustomerSmsStrategy implements MessageStrategy{

  @Override
  public void sendMessage(String message, String phone) {
    System.out.println(String.format("通过省级短信网关发送短信,message=[%s],"
        + "phone=[%s]", message, phone));
  }

}
  • Sms10086Strategy.java
package com.wangmengjun.tutorial.designpattern.strategy;

public class Sms10086Strategy implements MessageStrategy{

  @Override
  public void sendMessage(String message, String phone) {
    System.out.println(String.format("通过信息调度中心10086发送短信,message=[%s],"
        + "phone=[%s]", message, phone));
  }

}
  • MessageContext (Context)
package com.wangmengjun.tutorial.designpattern.strategy;

public class MessageContext {

  private MessageStrategy strategy;

  public MessageContext(MessageStrategy strategy) {
    this.strategy = strategy;
  }
  
  public void sendMessage(String message, String phone) {
    strategy.sendMessage(message, phone);
  }
  
}

模拟一下根据不同策略来完成简单的短信发送:

package com.wangmengjun.tutorial.designpattern.strategy;

public class StrategyMain {
  
  public static void main(String[] args) {
    String message = "Hello, Mengjun";
    String phone = "13675830509";
    
    MessageStrategy strategy  = new HySmsStrategy(); 
    System.out.println("1. HySmsStrategy -->");
    MessageContext context = new MessageContext(strategy);
    context.sendMessage(message, phone);
    
    System.out.println("2. CustomerSmsStrategy -->");
    strategy  = new CustomerSmsStrategy(); 
    context = new MessageContext(strategy);
    context.sendMessage(message, phone);
    
    System.out.println("3. Sms10086Strategy -->");
    strategy  = new Sms10086Strategy(); 
    context = new MessageContext(strategy);
    context.sendMessage(message, phone);
    
  }

}

输出结果如下:

1. HySmsStrategy -->
通过自主平台短信网关发送短信,message=[Hello, Mengjun],phone=[13675830509]
2. CustomerSmsStrategy -->
通过省级短信网关发送短信,message=[Hello, Mengjun],phone=[13675830509]
3. Sms10086Strategy -->
通过信息调度中心10086发送短信,message=[Hello, Mengjun],phone=[13675830509]

三、小结

3.1 适合策略模式使用的场景

策略模式是一种行为模式,其是对算法的封装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一些系列的策略类里面,作为一个抽象策略的子类。本模式使得算法可独立于使用它的客户而变化。

在下面的情况下应当考虑使用策略模式:

  1. 许多相关的类仅仅行为有异,使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  2. 一个系统的算法使用的数据不可以让客户知道。策略模式可以避免客户端涉及到不必要接触到的复杂和只与算法有关的数据。
  3. 如果一个对象有很多的行为,如果不使用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念

3.2 几个策略模式的例子

  • java.util.Comparator#compare(), executed by among others Collections#sort().
  • javax.servlet.http.HttpServlet, the service() and all doXXX() methods take HttpServletRequest and HttpServletResponse and the implementor has to process them (and not to get hold of them as instance variables!).
  • javax.servlet.Filter#doFilter()

使用策略模式,将行为封装在一个个独立的Strategy类中,可以消除一些条件语句等优点。但是,其也有不足之处,包括:

  • 客户端必须知道所有的策略,并自行决定使用哪一个策略。这就意味着客户端必须理解这些算法的区别。
  • 策略模式增加了很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略示例可以被不同客户端调用。换言之,可以使用享元模式来减少对象的数量。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档