一、何为策略模式

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

主要解决:在有多种算法相似的情况下,使用 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. Java的标识符,数据类型与各种运算符

    一.标识符 用作给变量.类和方法命名 java强调标识符有如下命名规则: 标识符必须以字母,下划线_,美元$开头 标识符其他部分可以是字母,下划线"_",美元符"$&qu ...

  2. cephfs创建及挂载

    Ceph 文件系统( Ceph FS )是个 POSIX 兼容的文件系统,它使用 Ceph 存储集群来存储数据.Ceph 文件系统要求 Ceph 存储集群内至少有一个 Ceph 元数据服务器. 1.添 ...

  3. IOS开发创建开发证书及发布App应用(三)——创建App ID

    3.创建App ID 继续上一篇所讲,今天写的这个是创建App ID 依然在个人中心创建证书这里, 如果不知道的,可以查看以前写的 点击左边的 Identifiers  下面的App IDs,如下图 ...

  4. Truncated incorrect DOUBLE value错误

    mysql报错:Truncated incorrect DOUBLE value sql的update语法错误eg: update Person set name = 'auhnayuiL' and ...

  5. 老李分享:接电话之uiautomator 1

    老李分享:接电话之uiautomator   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:9 ...

  6. Angular4.0.0发布总览文章

    翻译自angular.io上的关于4.0.0版本发布的文章,内容主要是介绍了4.0.0版本下的改进以及接下来还会有的其他更新,4.0.0其实已经出来好多天了,截止目前都已经到了4.0.1版本了,这也是 ...

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

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

  8. MySQL读写分离技术

    1.简介 当今MySQL使用相当广泛,随着用户的增多以及数据量的增大,高并发随之而来.然而我们有很多办法可以缓解数据库的压力.分布式数据库.负载均衡.读写分离.增加缓存服务器等等.这里我们将采用读写分 ...

  9. .Net Core MVC 过滤器(一)

    1.过滤器   过滤器运行在MVC Action Invocation Pipeline(MVC Action 请求管道),我们称它为Filter Pipleline(过滤器管道),Filter Pi ...

  10. Git命令行和Xcode结合使用

    现在一直使用Git来管理代码,对于有强迫症的我来说,依旧选择了命令行,下面这段话可以更好的解释我为什么喜欢使用终端敲命令. There are a lot of different ways to u ...