一、何为策略模式

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

主要解决:在有多种算法相似的情况下,使用 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. SERVLET中的doGet与doPost两个方法之间的区别

    get和post是http协议的两种方法,另外还有head, delete等 这两种方法有本质的区别,get只有一个流,参数附加在url后,大小个数有严格限制且只能是字符串.post的参数是通过另外的 ...

  2. 微软在.NET官网上线.NET 架构指南频道

    微软在Visual Studio 2017 正式发布的时候也上线了一个参考应用https://github.com/dotnet/eShopOnContainers , 最近微软给这个参考应用写了完善 ...

  3. (iOS)关于zbar扫描条形码,所搭载的设备

    四个月之前写的,现在发出来. 最近在开发一款程序的时候,功能要求扫描条形码. 现在最流行的扫描条形码的开源代码有zbar和zxing两种,可以支持多种一维和二维码. 之前了解过zbar,所以这次试用z ...

  4. 什么是NoSQL

    NoSQL = Not Only SQL 不仅仅是SQL NoSQL,指的是非关系型的数据库(没有声明性查询语言,没有预定义的模式,可以为键 - 值对存储,列存储,文档存储,图形数据库).不同于传统的 ...

  5. 数据库问题(程序连接mysql错误)

    今天服务器遇到了一个很熟悉的问题 输入 #mysql -u root -p ERROR 2002 (HY000):Can't connect to local MySQL server 随即上网找寻答 ...

  6. memory库函数的实现

    下面主要对常用的几个memory库函数的实现(memcpy.memmove.memset.memcmp): memcpy函数与memmove函数: 相同点: 两者实现的功能均为从src拷贝count个 ...

  7. java线程控制方法

    一.中断线程 1.Thread.sleep()让线程进入睡眠状态,放弃CPU的占用暂停若干毫秒使用方法: public class runable implements Runnable { @Ove ...

  8. SQLite中使用CTE巧解多级分类的级联查询

    在最近的项目中使用ActiveReports报表设计器设计一个报表模板时,遇到一个多级分类的难题:需要将某个部门所有销售及下属部门的销售金额汇总,因为下属级别的层次不确定,所以靠拼接子查询的方式显然是 ...

  9. C#,VB.NET如何将Word转换为PDF和Text

    众所周知,Word是我们日常工作中常用的办公软件之一,有时出于某种需求我们需要将Word文档转换为PDF以及Text.那么如何以C#,VB.NET编程的方式来实现这一功能呢? 下面我将分开介绍如何运用 ...

  10. (一)java多线程之Thread

    本人邮箱: kco1989@qq.com 欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kco github: https://github.com/kco198 ...