一、何为策略模式

策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式。也称为政策模式

主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。

应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。

优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。

使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

二、策略模式的UML图

抽象策略类(Strategy):定义一个所有算法都支持的通用接口,内容类使用这个接口调用由具体策略实现的算法。

具体策略类(OperationAdd、OperationSubstract、OperationMultiply):实现一个相应的算法

内容类(Context):包含一个对策略对象的引用,可定义一个用于策略类访问的接口。当需要进行特定的操作时会从对应的策略类对象调用相应的算法。内容类本身不会察觉对策略类的执行。如果有必要的话,还可以定义专用的对象来传递从内容类对象到策略类的数据。内容类接受来自客户端的数据,并将其委托给策略类对象。而策略类通常是客户端创建,并传递给内容类。

三、策略类的应用场景及创建步骤

在计算机算法中,我们可以实现对列表中数据的排序,其方法有冒泡排序、快速排序、堆排序等不同的算法。然而在实际运用中则一次只使用其中的一个算法。为了在不同的场景中权衡计算机的运算速度和存储空间大小等,可以使用不同的算法。

再比如,我们乘车去某地,可以选择出租、大巴、城市交通工具等等方式,每种方式在费用、便利性、时间等成本上具有不同,我们会根据不同的场合选用不同的策略。

接下来,我们看一下策略模式的创建步骤

1)识别客户端可能需要的算法。既然是对算法策略的选择,第一步必当是算法的识别

2)在接口中指定该算法的签名(原型定义)。

3)在派生类中提供可选择的细节。即对算法的具体实现

4)将客户端算法与接口耦合。即在客户端中通过不同场合下的判断决定调用不同策略类提供的算法

四、某个具体的实现案例

在这里,我们看一个关于推送的案例。在现在电商无比潇洒的光景下,各大电商为了迎合自己客户的需求,希望提供自己服务的质量。于是,在用户打开他们客户端的时刻,他们便急于将自己的产品推送给客户。于是产生了问题----客户想要什么。不同的客户有不同的需求,不能只推送电商自己想要急于出售的东西。于是电商们建立了自己的数据引擎,希望通过对客户历史上的商品浏览记录、购买记录来预知客户的需求。

首先对上段文字做一个小小的分析,上面涉及到了诸如客户(Customer)、引擎(Engine)等实体,我们可以此建立我们的类。而引擎需要获取客户的相关数据,因此需要客户提供给引擎一个可访问的接口。而引擎负责给客户提供数据支持,为了掩盖不同引擎的差别,也应当提供一个引擎的接口。

然而,客户或许未能登录,或许第一次进入系统而没有相关的浏览数据信息,该怎么办呢?

需要不同的引擎支持。

由此我们建立UML图进一步分析

如图所示,我们建立了对客户(Customer)的接口ICustomer,对策略类的接口IAdvisor。

假设有三个数据引擎:

RefEngine:针对登录用户能够根据引用到的客户信息来推送客户想要的数据信息

OtherRecEngine:其他推荐引擎,指的是对于登录的用户,虽然能够获取用户的一些信息但是由于用户的商品信息过少或者其他原因,通过一些供货商(vender)进行主动推送

RandomEngine:随机引擎,当没有足够的数据提供给另外两个引擎时(用户都未曾登录),使用随机生成推送的方法推送信息

注:由于三个引擎只使用其算法实现,故均只生成单例

下面,我们对该实例进行实现。

五、具体实现

1.对客户及对推送引擎接口的实现

1.1 Java实现

引擎接口

 public interface IAdvisor {
public Object Recommend(Customer c);
}

客户接口

 public interface ICustomer {
public String getInfo();
}

1.2 c#实现

引擎接口

 interface IAdvisor
{
Object Recommend(Customer c);
}

客户接口

 interface ICustomer
{
String getInfo();
}

2.对三个引擎的实现(策略类)

注:由于每个引擎只需使用其中的算法实例,故每个引擎只需存在单一实例,通过简单的方法实现单例

2.1 Java实现

 public class OtherRecEngine implements IAdvisor{
//Using Singleton pattern to only generate one instance
public static final OtherRecEngine singleton=new OtherRecEngine(); private OtherRecEngine(){}; //using Engine to generate outcome with the info of customer
public Object Recommend(Customer c){
return new String("Using OtherRecEngine to generate outcome with the infomation of the customer: \""+c.getInfo()+"\"");
} }
 public class RefEngine implements IAdvisor{
//Using Singleton pattern to only generate one instance
public static final RefEngine singleton=new RefEngine(); private RefEngine(){} //using Engine to generate outcome with the info of customer
public Object Recommend(Customer c){
return new String("Using RefEngine to generate outcome with the infomation of the customer: \""+c.getInfo()+"\"");
}
}
 public class RandomEngine implements IAdvisor{
//Using Singleton pattern to only generate one instance
public static final RandomEngine singleton=new RandomEngine(); private RandomEngine(){}; //Generate outcome with no info
public Object Recommend(Customer c){
return new String("Generate using Random Engine");
}
}

2.2 c#实现

 class RefEngine : IAdvisor
{
//Using singleton pattern for just on instance of this class
public static readonly RefEngine singleton = new RefEngine(); private RefEngine() { } //using Engine to generate outcome with the info of customer
public object Recommend(Customer c)
{
return "Using RefEngine to generate outcome with the infomation of the customer: \"" + c.getInfo() + "\"";
}
}
 class OtherRecEngine:IAdvisor
{
//Using Singleton pattern to only generate one instance
public static readonly OtherRecEngine singleton = new OtherRecEngine(); private OtherRecEngine() { } //using Engine to generate outcome with the info of customer
public object Recommend(Customer c)
{
return "Using OtherRecEngine to generate outcome with the infomation of the customer: \"" + c.getInfo() + "\"";
}
}
 class RandomEngine : IAdvisor
{
//Using Singleton pattern to only generate one instance
public static readonly RandomEngine singleton = new RandomEngine(); private RandomEngine() { } //Generate outcome with no info
public object Recommend(Customer c)
{
return "Generate using Random Engine";
}
}

3.实现客户类

在客户类的实现中通过showAdvices该方法获取从引擎传来的数据,而不同的场景下选择的引擎不同,故通过场景的判断来实现对不同场景的判断并通过获取到的引擎实例来获得推送消息

3.1 Java实现

 public class Customer implements ICustomer{
public Customer(){};
//the stategy
private IAdvisor _advisor; //info:Customer's infomation login:if Customer login
private String info;
private boolean login=false; //if vender propel info
private boolean venderSuggest=false; //Using the Strategy
public void showAdvices(){
if(_advisor==null){
if(login==true){
_advisor=RefEngine.singleton;
}
else if(venderSuggest==true){
_advisor=OtherRecEngine.singleton;
}
else
_advisor=RandomEngine.singleton;
}
System.out.println(_advisor.Recommend(this));
} public boolean isLogin(){
return login;
} public void Login(){
login=true;
} public boolean isVenderSuggest(){
return venderSuggest;
} public void setVenderSuggest(boolean b){
venderSuggest=b;
} public String getInfo(){
return "I'm a customer";
} }

3.2 c#实现

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Strategy
{
class Customer:ICustomer
{
private IAdvisor _advisor;
private string info;
private bool login = false;
private bool venderSuggest=false; public Customer() { }
//If vender have something to recommend to customer
public bool VenderSuggest
{
get
{
return venderSuggest;
} set
{
venderSuggest = value;
}
}
//if customer logged in
public void Login()
{
login = true;
} //Execute the strategy
public void showAdvices()
{
if (_advisor == null)
{
if (login == true)
{
_advisor = RefEngine.singleton;
}
else if (venderSuggest == true)
{
_advisor = OtherRecEngine.singleton;
}
else
_advisor = RandomEngine.singleton;
}
Console.WriteLine(_advisor.Recommend(this));
} //get the info of customer
public string getInfo()
{
return "I'm a customer";
}
}
}

4.客户端(控制台)调用

4.1 Java实现

 public class Program {
public static void main(String[] args){ //Initialize customers
Customer c1=new Customer();
c1.Login();
c1.setVenderSuggest(true); Customer c2=new Customer();
c2.setVenderSuggest(true); Customer c3=new Customer(); c1.showAdvices();
c2.showAdvices();
c3.showAdvices();
}
}

运行实例:

4.2 c#实现

 class Program
{
static void Main(string[] args)
{
//Initialize all customers
Customer c1 = new Customer();
c1.Login(); Customer c2 = new Customer()
{
VenderSuggest =true
}; Customer c3 = new Customer(); c1.showAdvices();
c2.showAdvices();
c3.showAdvices();
}
}

运行实例:

设计模式浅谈----策略模式(c#及java实现)的更多相关文章

  1. 《Head First 设计模式》[01] 策略模式

    <Head First 设计模式>(点击查看详情) 1.写在前面的话 之前在列书单的时候,看网友对于设计模式的推荐里说,设计模式的书类别都大同小异,于是自己就选择了Head First系列 ...

  2. 浅谈MVVM模式和MVP模式——Vue.js向

    浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...

  3. Python设计模式: 最佳的"策略"模式实践代码

    Python设计模式: 最佳的"策略"模式实践代码 今天抽空看了下流畅的python,发现里面介绍了不少python自带的库的使用实例,用起来非常的优雅. 平时用Python来写爬 ...

  4. 【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成 ...

  5. 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...

  6. javascript设计模式--策略模式

    javascript策略模式总结 1.什么是策略模式? 策略模式的定义是:定义一系列的算法,把他们独立封装起来,并且可以相互替换. 例如我们需要写一段代码来计算员工的奖金.当绩效为a时,奖金为工资的5 ...

  7. [head first 设计模式] 第一章 策略模式

    [head first 设计模式] 第一章 策略模式 让我们先从一个简单的鸭子模拟器开始讲起. 假设有个简单的鸭子模拟器,游戏中会出现各种鸭子,此系统的原始设计如下,设计了一个鸭子超类,并让各种鸭子继 ...

  8. 设计模式之——浅谈strategy模式(策略模式)

    strategy模式,即策略模式.个人觉得吧,策略模式更多的是一种思维方式. 首先我们要知道,为什么需要策略模式.举个例子,比如用程序输出今天下午去玩什么. PlayGame 玩游戏 package ...

  9. Java进阶篇设计模式之十一 ---- 策略模式和模板方法模式

    前言 在上一篇中我们学习了行为型模式的访问者模式(Visitor Pattern)和中介者模式(Mediator Pattern).本篇则来学习下行为型模式的两个模式,策略模式(Strategy Pa ...

随机推荐

  1. HTMLElement

    参考文档:MDN HTMLElement 一.继承关系 所有HTML元素都是由HTMLElement或者其更具体的子类型来表示的. HTMLElement继承自Element,并实现了GlobalEv ...

  2. 使用register_shutdown_function触发写日志,使用fastcgi_finish_request提高响应速度

    公司内部的市场管理系统,一直是我一个人维护,最近老是有开发埋怨,内网的账号被人改了密码,账号被解绑了...哈的,错在这还不是一个完整的系统,既没有严格的权限也没有做操作日志呀... 权限现在是准备做在 ...

  3. HTML5 WebSocket和后端C#通信

    1.使用 HTML5 开发离线应用 http://www.ibm.com/developerworks/cn/web/1011_guozb_html5off/ 2.利用html 5 websocket ...

  4. 【转】Eclipse 如何添加Android SDK

      问题描述: 如何为Eclipse编程软件添加Android SDK功能,使其能进行Android开发. 解决方法: 软件版本:Eclipse 3.7,installer_r18-windows.e ...

  5. 老李分享:持续集成学好jenkins之解答疑问

    老李分享:持续集成学好jenkins之解答疑问   poptest(www.poptest.cn)在培训的过程中使用jenkins搭建持续集成环境,让学员真正交流持续集成到底是什么,怎么去做的. Je ...

  6. cassandra高级操作之JMX操作

    需求场景 项目中有这么个需求:统计集群中各个节点的数据量存储大小,不是记录数. 一开始有点无头绪,后面查看cassandra官方文档看到Monitoring章节,里面说到:Cassandra中的指标使 ...

  7. Python__slots__详解

    摘要 当一个类需要创建大量实例时,可以通过__slots__声明实例所需要的属性, 例如,class Foo(object): __slots__ = ['foo'].这样做带来以下优点: 更快的属性 ...

  8. 使用Jersey实现图片服务器与应用服务器分离

         现在模拟一下Jersey从客户端发送图片到服务器.   1.Tomcat准备 (1)解压一个新的Tomcat作为图片服务器,然后修改端口号(有3处).                (2)然 ...

  9. 常用SQL_官方文档使用

    SQL语句基础理论 SQL是操作和检索关系型数据库的标准语言,标准SQL语句可用于操作关系型数据库. 5大主要类型: ①DQL(Data Query Language,数据查询语言)语句,主要由于se ...

  10. 1102: 零起点学算法09——继续练习简单的输入和计算(a-b)

    1102: 零起点学算法09--继续练习简单的输入和计算(a-b) Time Limit: 1 Sec  Memory Limit: 520 MB   64bit IO Format: %lldSub ...