设计模式浅谈----策略模式(c#及java实现)
一、何为策略模式
策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式。也称为政策模式。
主要解决:在有多种算法相似的情况下,使用 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实现)的更多相关文章
- 《Head First 设计模式》[01] 策略模式
<Head First 设计模式>(点击查看详情) 1.写在前面的话 之前在列书单的时候,看网友对于设计模式的推荐里说,设计模式的书类别都大同小异,于是自己就选择了Head First系列 ...
- 浅谈MVVM模式和MVP模式——Vue.js向
浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...
- Python设计模式: 最佳的"策略"模式实践代码
Python设计模式: 最佳的"策略"模式实践代码 今天抽空看了下流畅的python,发现里面介绍了不少python自带的库的使用实例,用起来非常的优雅. 平时用Python来写爬 ...
- 【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成 ...
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...
- javascript设计模式--策略模式
javascript策略模式总结 1.什么是策略模式? 策略模式的定义是:定义一系列的算法,把他们独立封装起来,并且可以相互替换. 例如我们需要写一段代码来计算员工的奖金.当绩效为a时,奖金为工资的5 ...
- [head first 设计模式] 第一章 策略模式
[head first 设计模式] 第一章 策略模式 让我们先从一个简单的鸭子模拟器开始讲起. 假设有个简单的鸭子模拟器,游戏中会出现各种鸭子,此系统的原始设计如下,设计了一个鸭子超类,并让各种鸭子继 ...
- 设计模式之——浅谈strategy模式(策略模式)
strategy模式,即策略模式.个人觉得吧,策略模式更多的是一种思维方式. 首先我们要知道,为什么需要策略模式.举个例子,比如用程序输出今天下午去玩什么. PlayGame 玩游戏 package ...
- Java进阶篇设计模式之十一 ---- 策略模式和模板方法模式
前言 在上一篇中我们学习了行为型模式的访问者模式(Visitor Pattern)和中介者模式(Mediator Pattern).本篇则来学习下行为型模式的两个模式,策略模式(Strategy Pa ...
随机推荐
- Zabbix3.0部署最佳实践
Zabbix3整个web界面做了一个全新的设计. 更多新特性请点击当前字幕查看 笔者QQ:572891887 Linux架构交流群:471443208 1.1Zabbix环境准备 [root@li ...
- piwik安装部署最佳实践
1.piwik介绍 Piwik是一个PHP和MySQL的开放源代码的Web统计软件,它给你一些关于你的网站的实用统计报告,比如网页浏览人数,访问最多的页面,搜索引擎关键词等等. Piwik拥有众多不同 ...
- asp.net core源码飘香:Options组件
简介: Options组件是一个小组件,但用的地方很多.它本质是将一个POCO类注册到容器中(主要在Startup中作为其他组件的配置功能提供),后续使用的时候就可以通过比如构造函数注入等获取到POC ...
- 数字图像处理(MATLAB版)学习笔记(2)——第2章 灰度变换与空间滤波
0.小叙闲言 1.本章整体结构 2.书中例子 例2.1 主要是使用函数imadjust,来熟悉一下灰度处理,体验一把 >> imread('myimage.jpg'); >> ...
- VS 2017 Git failed with a fatal error的解决办法
前几天,满怀欣喜的从VS2015更新到了VS2017,经过这几天的试用,整体来说感觉还是挺不错的.昨天推送项目到远程服务器的时候,发现出现了推送失败的错误,错误如图: 按照提示,我看到输出窗口的输入内 ...
- ML(4): NavieBayes在R中的应用
朴素贝叶斯方法是一种使用先验概率去计算后验概率的方法, 具体见上一节. 算法包:e1071 函数:navieBayes(formule,data,laplace=0,...,subset,na.act ...
- 转账示例(三):service层面实现(线程管理Connection)(本例采用QueryRunner来执行sql语句,数据源为C3P0)
缺点:Service层面还是不应该出现关于事务的操作1.自行创建C3P0Uti,account数据库,导入Jar包 2.Dao层面 接口: package com.learning.dao; impo ...
- node.js 中模块的循环调用问题详解
首先,我们看一下图示代码,每一个注释其实代表一个 js 文件.所以下面其实是三个 js 文件 .第一个是我们要运行的 main 文件,后面两个是 a, b 文件. 从上面可以看书 a ,b 两个模 ...
- 想询问一个职业规划的问题,前端开发 or nodejs?
先说说个人情况,目前个人定位于初中级前端吧,工作近两年,目前前端开发和nodejs都有一定的了解,水平感觉可以搭一些小型的网站.作为前端开发,目前掌握的技术是javascript,平时更多的是用jqu ...
- Linux--shell脚本之文本处理工具
文本处理工具--grep.sed.awk Bash Shell提供了功能强大的文件处理工具:sed(流编辑器stream editor)和awk,都可使用正则表达式进行模式匹配. 而grep又有助于理 ...