设计模式18---设计模式之策略模式(Strategy)(行为型)
1.场景模拟
简单的报价管理系统:
对于普通用户和新用户报全价
对于老客户统一折扣5%
对于大客户统一折扣10%
2.不用模式的解决方案
- package demo16.strategy.example2;
- /**
- * 价格管理,主要完成计算向客户所报价格的功能
- */
- public class Price {
- /**
- * 报价,对不同类型的,计算不同的价格
- * @param goodsPrice 商品销售原价
- * @param customerType 客户类型
- * @return 计算出来的,应该给客户报的价格
- */
- public double quote(double goodsPrice,String customerType){
- if("普通客户".equals(customerType)){
- return this.calcPriceForNormal(goodsPrice);
- }else if("老客户".equals(customerType)){
- return this.calcPriceForOld(goodsPrice);
- }else if("大客户".equals(customerType)){
- return this.calcPriceForLarge(goodsPrice);
- }
- //其余人员都是报原价
- return goodsPrice;
- }
- /**
- * 为新客户或者是普通客户计算应报的价格
- * @param goodsPrice 商品销售原价
- * @return 计算出来的,应该给客户报的价格
- */
- private double calcPriceForNormal(double goodsPrice){
- System.out.println("对于新客户或者是普通客户,没有折扣");
- return goodsPrice;
- }
- /**
- * 为老客户计算应报的价格
- * @param goodsPrice 商品销售原价
- * @return 计算出来的,应该给客户报的价格
- */
- private double calcPriceForOld(double goodsPrice){
- System.out.println("对于老客户,统一折扣5%");
- return goodsPrice*(1-0.05);
- }
- /**
- * 为大客户计算应报的价格
- * @param goodsPrice 商品销售原价
- * @return 计算出来的,应该给客户报的价格
- */
- private double calcPriceForLarge(double goodsPrice){
- System.out.println("对于大客户,统一折扣10%");
- return goodsPrice*(1-0.1);
- }
- }
3.有何问题?
会经常有这样的需要,在公司周年庆的时候,所有的客户额外增加3%的折扣,在换季的时候普通用户额外增加3%的折扣,然后过了促销时间,价格又要涨回来,那么这个价格类将会非常的庞大,而且,方法非常的多。
看到这,朋友们很快就想到:如何实现才能让价格类中的计算报价的算法,很容易的实现可维护,可扩展,而且可以动态的切换变化呢?
4.使用策略模式来解决问题
4.1策略模式定义
定义一系列的算法,把他们一个个封装起来,并且可以使他们相互替换,本模式使得算法可独立于使用它的客户而变化。
4.2策略模式的结构图
4.3策略模式示例代码
- package demo16.strategy.example3;
- /**
- * 策略,定义算法的接口
- */
- public interface Strategy {
- /**
- * 某个算法的接口,可以有传入参数,也可以有返回值
- */
- public void algorithmInterface();
- }
- *********************************************************************
- package demo16.strategy.example3;
- /**
- * 实现具体的算法
- */
- public class ConcreteStrategyA implements Strategy {
- public void algorithmInterface() {
- //具体的算法实现
- }
- }
- *********************************************************************
- package demo16.strategy.example3;
- /**
- * 实现具体的算法
- */
- public class ConcreteStrategyB implements Strategy {
- public void algorithmInterface() {
- //具体的算法实现
- }
- }
- package demo16.strategy.example3;
- /**
- * 实现具体的算法
- */
- public class ConcreteStrategyC implements Strategy {
- public void algorithmInterface() {
- //具体的算法实现
- }
- }
- *********************************************************************
- package demo16.strategy.example3;
- /**
- * 上下文对象,通常会持有一个具体的策略对象
- */
- public class Context {
- /**
- * 持有一个具体的策略对象
- */
- private Strategy strategy;
- /**
- * 构造方法,传入一个具体的策略对象
- * @param aStrategy 具体的策略对象
- */
- public Context(Strategy aStrategy) {
- this.strategy = aStrategy;
- }
- /**
- * 上下文对客户端提供的操作接口,可以有参数和返回值
- */
- public void contextInterface() {
- //通常会转调具体的策略对象进行算法运算
- strategy.algorithmInterface();
- }
- }
5.使用策略模式重写实例
- package demo16.strategy.example4;
- /**
- * 策略,定义计算报价算法的接口
- */
- public interface Strategy {
- /**
- * 计算应报的价格
- * @param goodsPrice 商品销售原价
- * @return 计算出来的,应该给客户报的价格
- */
- public double calcPrice(double goodsPrice);
- }
- ************************************************************************
- package demo16.strategy.example4;
- /**
- * 具体算法实现,为新客户或者是普通客户计算应报的价格
- */
- public class NormalCustomerStrategy implements Strategy{
- public double calcPrice(double goodsPrice) {
- System.out.println("对于新客户或者是普通客户,没有折扣");
- return goodsPrice;
- }
- }
- ***********************************************************************
- package demo16.strategy.example4;
- /**
- * 具体算法实现,为老客户计算应报的价格
- */
- public class OldCustomerStrategy implements Strategy{
- public double calcPrice(double goodsPrice) {
- System.out.println("对于老客户,统一折扣5%");
- return goodsPrice*(1-0.05);
- }
- }
- ***********************************************************************
- package demo16.strategy.example4;
- /**
- * 具体算法实现,为大客户计算应报的价格
- */
- public class LargeCustomerStrategy implements Strategy{
- public double calcPrice(double goodsPrice) {
- System.out.println("对于大客户,统一折扣10%");
- return goodsPrice*(1-0.1);
- }
- }
- ***********************************************************************
- package demo16.strategy.example4;
- /**
- * 价格管理,主要完成计算向客户所报价格的功能
- */
- public class Price {
- /**
- * 持有一个具体的策略对象
- */
- private Strategy strategy = null;
- /**
- * 构造方法,传入一个具体的策略对象
- * @param aStrategy 具体的策略对象
- */
- public Price(Strategy aStrategy){
- this.strategy = aStrategy;
- }
- /**
- * 报价,计算对客户的报价
- * @param goodsPrice 商品销售原价
- * @return 计算出来的,应该给客户报的价格
- */
- public double quote(double goodsPrice){
- return this.strategy.calcPrice(goodsPrice);
- }
- }
- ***********************************************************************
- package demo16.strategy.example4;
- public class Client {
- public static void main(String[] args) {
- //1:选择并创建需要使用的策略对象
- Strategy strategy = new LargeCustomerStrategy();
- //2:创建上下文
- Price ctx = new Price(strategy);
- //3:计算报价
- double quote = ctx.quote(1000);
- System.out.println("向客户报价:"+quote);
- }
- }
6.模式讲解
6.1要点
功能:把具体的算法从具体的业务处理中独立出来,把他们实现成为单独的算法类,从而形成一系列的算法,并让这些算法可以相互替换。
策略算法是相同行为的不同实现
什么时候选用:多个if-else语句的时候就可以选用
6.2策略模式的调用顺序示意图
首先客户端选择并创建具体的策略对象
其次创建上下文
最后调用上下文的方法来执行功能了
6.3当添加新的策略时候
只需要动下面代码,是不是很简单,很方便呢?
//1:选择并创建需要使用的策略对象
Strategy strategy = new LargeCustomerStrategy();
6.4另一种策略模式调用示意图
6.5策略模式优缺点
优点:定义一系列算法,避免使用多重条件语句,更好的扩展性
缺点:客户端必须了解每种策略的不同,增加了对象数目,只适合扁平的算法结构(地位平等的算法)
6.6设计模式的本质
分离算法,选择实现
设计模式18---设计模式之策略模式(Strategy)(行为型)的更多相关文章
- 设计模式(二)策略模式(Strategy)
1.分析项目中变化部分与不变部分 2.多用组合,少用继承:用行为类组合,而不是行为的继承 案例: 第一步,把行为抽象为接口 package top.littlepage.designPattern.S ...
- HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern)
策略模式(Strategy Pattern): 定义了了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户端. 第一个设计原则:找出应用中可能需要变化之处,把他们独立 ...
- 设计模式(二) 策略模式Strategy
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,我个人的理解是,具有相同行为不同的行为模式,比如走路,有人速度3m/s,有人100m/s,把他们的具体行走和对象本身 ...
- Headfirst设计模式的C++实现——策略模式(Strategy)
前言 最近在学习<Headfirst设计模式>,里面的例子都是Java的.但是我对Java并不熟悉,所以试着用C++来实现书中的例子. 先来看看Duck以及子类 Duck.h #inclu ...
- 设计模式(一):“穿越火线”中的“策略模式”(Strategy Pattern)
在前段时间呢陆陆续续的更新了一系列关于重构的文章.在重构我们既有的代码时,往往会用到设计模式.在之前重构系列的博客中,我们在重构时用到了“工厂模式”.“策略模式”.“状态模式”等.当然在重构时,有的地 ...
- 【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成 ...
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...
- 反馈法学习设计模式(一)——策略模式Strategy Pattern
简介(Introduction) 之前学习Java8实战时,遇到一个很好的策略模式示例.便想着借着这个示例结合反馈式的方法来,学习策略设计模式,也以便后面反复琢磨学习. 首先我们通过练习,逐步写出符合 ...
- JavaScript设计模式 Item 7 --策略模式Strategy
1.策略模式的定义 何为策略?比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但是不在乎钱,可以选择坐飞机. 如果没有钱,可以选择坐大巴或者火车. 如果再穷一点,可以选 ...
随机推荐
- java线 生产者和消费者
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlhbmdydWkxOTg4/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- WebAPI 和 WebService的区别
webapi用的是http协议,webservice用的是soap协议 webapi无状态,相对webservice更轻量级.webapi支持如get,post等http操作 http soap关系 ...
- java web.xml listener servlet 和filter加载顺序
在该项目中总会遇到一些关于加载的优先问题.最近遇到了同样的类别似的,所以,如果你发现信息汇总下,以下是转载其他一些人,毕竟,人们写的不错.它不重复创建的轮.只是略作修改自己的观点. 首先能够肯定的是, ...
- linux虚拟文件系统2
转自:http://rstevens.iteye.com/blog/849413 一.概述 Linux 文件系统是相当复杂的,本文只分析虚拟文件系统的实现,对具体的文件系统不涉及. 即使是虚拟文件系统 ...
- WebBrowser控件的简单应用2
原文:WebBrowser控件的简单应用2 第一个简单应用里面讲述的是如何模拟调用当前网页的元素的事件或者赋值/取值.这次的应用讲述的是1:如何处理弹出新页面的事件(总是在我的浏览器里面现实新页面)2 ...
- Hadoop与HBase中遇到的问题(续)java.io.IOException: Non-increasing Bloom keys异常
在使用Bulkload向HBase导入数据中, 自己编写Map与使用KeyValueSortReducer生成HFile时, 出现了以下的异常: java.io.IOException: Non-in ...
- GCD && Run Loops学习笔记
1.GCD 使用不同优先级的若干个队列乍听起来非常直接,只是,我们强烈建议,在绝大多数情况下使用默认的优先级队列就能够了.假设运行的任务须要訪问一些共享的资源,那么在不同优先级的队列中调度这些任务非常 ...
- jQuery 添加 删除 改动select option
jQuery获取Select选择的Text和Value: 1. var checkText=jQuery("#select_id").find("option:selec ...
- C# 带滚动栏的Label控件
C# 带滚动栏的Label控件,用鼠标选的时候还是有点闪烁: namespace 带滚动栏的Label控件 { public class TextBoxLabel : System.Windows.F ...
- JavaScript重载解读
在JavaScript有一个特殊的数据类型---Function种类,JavaScript每个功能Function的类型,例如可以.由于函数是对象.指针,不会与某个函数绑定. <pre name ...