一、何为策略模式

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

主要解决:在有多种算法相似的情况下,使用 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. crontab的定时任务不能自动执行,但是手动执行脚本一直能成功

    crontab 问题小记: 环境变量问题, 养成良好的习惯, 在脚本开头export PATH 原因是 crontab 执行定时任务时,用的不是系统环境变量,而是自己的环境变量,可以把 echo $P ...

  2. 浅谈Java的开放封闭原则

    写在前面 最近, 接手了一个新业务,系统的架构可圈可点.但有些地方让人望而生畏,有些代码臃肿难以维护,让人不敢恭维.于是,结合了Java的开放封闭原则,对其中一部分代码进行了重构优化. 先来看下以前系 ...

  3. Java基础之J2EE规范

    什么是J2EE? 在企业级应用中,都有一些通用企业需求模块,如数据库连接,邮件服务,事务处理等.既然很多企业级应用都需要这些模块,一些大公司便开发了自己的通用模块服务,即中间件.这样一来,就避免了重复 ...

  4. D3.js-坐标轴生成测试SVG

    Bottom top Bottom top   // =0) return "translate("+margin+","+i*offset+")&q ...

  5. Java并发基础:进程和线程之由来

    转载自:http://www.cnblogs.com/dolphin0520/p/3910667.html 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程. ...

  6. DCN路由操作

    offset */interface in/out access-list/prefix-list <1-16>                 // 修改路由偏移量   RIP偏移列表 ...

  7. MyBatis 源码分析——动态SQL语句

    有几年开发经验的程序员应该都有暗骂过原生的SQL语句吧.因为他们不能一句就搞定一个业务,往往还要通过代码来拼接相关的SQL语句.相信大家会理解SQL里面的永真(1=1),永假(1=2)的意义吧.所以m ...

  8. Java ---自定义标签(二)

    上篇文章的最后,我们自定义了一个带属性的标签,并使用它完成了一个简单的案例.其实到这我们已经可以看出来,前端jsp页面只需要写一个类似html语法的标签,就可以完成将集合中的数据取出来并展示这么相对复 ...

  9. Redis基础学习(三)—Key操作

    一.key的相关操作 1.删除 del key1 key2 ... Keyn 作用: 删除1个或多个键. 返回值: 不存在的key忽略掉,返回真正删除的key的数量.   2.重命名 rename k ...

  10. MYSQL PGA SGA设置

    mysql使用总内存 = global_buffers + thread_buffers All thread buffer(会话/线程级内存分配总和) = max_threads(当前活跃连接数)  ...