策略模式

策略模式的定义是:定义了一系列的算法,把它们一个个的封装起来,并且使它们可相互替换,让算法可以独立于使用它的客户而变化。

设计原则是:把一个类中经常改变或者将来可能会经常改变的部分提取出来作为一个接口,然后在使用类中包含这个接口的实例,这样使用类的对象就可以随意调用实现了这个接口的类行为。

在策略模式中有如下几个角色:

环境角色(Context): 此角色中实现了对策略角色的引用和使用。

抽象策略角色:此角色通常由抽象类或接口来实现,定义了,所以具体策略角色的行为。

具体策略角色:此角色封装了实现不同功能的不同算法。

演示代码如下:

抽象策略类

public interface Strategy {
/**
* 策略方法
*/
void strategyMethod();
}

具体角色类A

public class ConcreteStrategyA implements Strategy{

    @Override
public void strategyMethod() {
//具体的行为
}
}

具体角色类B

public class ConcreteStrategyB implements Strategy {
@Override
public void strategyMethod() {
//具体的行为
}
}

环境角色类

public class Context {
/**
* 持有一个具体的策略对象
*/
private Strategy strategy; /**
* 构造方法,传入一个具体的策略对象
* @param strategy 具体的策略对象
*/
public Context(Strategy strategy)
{
this.strategy = strategy;
} /**
* 对外提供的使用策略的方法
*/
public void contextMethod()
{
//通常会转调具体的策略对象进行算法运算
strategy.strategyMethod();
}
}

策略模式具体场景例子

某Saas公司的企业服务系统,在销售时,会根据客户的购买时长来确定优惠策略,分为普通客户(无优惠政策),大客户(98折),战略客户(95折)。普通客户是指一次性租用服务在一到3年之间的,大客户指一次性使用服务3到5年之间的,战略客户指一次性使用服务5年以上的。因为每种客户价格算法不同,所以这个场景就可以使用策略模式。

定义一个计算价格行为的接口

public interface SalePrice {
/**
* 根据原价返回不同的价格
* @param originalPrice 原始价格
* @return
*/
BigDecimal salePrice(BigDecimal originalPrice);
}

然后定义三中客户的具体计算价格类(策略类)

public class OriginalCustomer implements SalePrice {
/**
* 普通客户直接返回原价
* @param originalPrice 原始价格
* @return 计算后的价格
*/
@Override
public BigDecimal salePrice(BigDecimal originalPrice) { return originalPrice.multiply(BigDecimal.valueOf(1));
}
}
public class LargeCustomer implements SalePrice {
/**
* 大客户返回98折价格
* @param originalPrice 原始价格
* @return 计算后的价格
*/
@Override
public BigDecimal salePrice(BigDecimal originalPrice) { return originalPrice.multiply(BigDecimal.valueOf(0.98));
}
}
public class StrategicCustomer implements SalePrice {
/**
* 战略客户直接返回95折价格
* @param originalPrice 原始价格
* @return 计算后的价格
*/
@Override
public BigDecimal salePrice(BigDecimal originalPrice) {
return originalPrice.multiply(BigDecimal.valueOf(0.95));
}
}

客户类,需要判断具体的调用哪个计算价格的方法

public class Customer {

    private int years;
/** 租用服务一年的初始价格 */
private BigDecimal originalPrice = BigDecimal.valueOf(50000);
/** 客户最终支付的价格 **/
private BigDecimal payForPrice = BigDecimal.ZERO;
/** 每个客户的初始价格都是原价 */
private SalePrice salePrice = new OriginalCustomer(); /**
* 根据客户购买的时长来计算每一年的优惠价格(单位:年)
* @param years
*/
public void buy(int years)
{
this.years = years;
payForPrice = originalPrice.multiply(BigDecimal.valueOf(years));
//大于5年的战略客户价格
if(years >= 5){
salePrice = new StrategicCustomer();
}else if(years >= 3)//3年到5年的大客户优惠价格
{
salePrice = new LargeCustomer();
}else if(years >= 1)//1到3年的普通用户原价
{
salePrice = new OriginalCustomer();
}
} /**
* 计算客户最终支付的价格
* @return
*/
public BigDecimal payPrice(){
return salePrice.salePrice(payForPrice);
} }

客户端调用类,自动计算支付价格

**
* 客户端调用类
*/
@Slf4j
public class Client { public static void main(String[] args){
Customer customer = new Customer(); customer.buy(1);
log.info("客户需支付:{}",customer.payPrice()); customer.buy(3);
log.info("客户需支付:{}",customer.payPrice()); customer.buy(6);
log.info("客户需支付:{}",customer.payPrice()); }
}

输出结果:

客户需支付:50000
客户需支付:147000.00
客户需支付:285000.00

根据输出结果可以看出购买不同时间的服务,收费价格是不同的。这样客户可以不用依赖具体的收费方法,直接根据需要的服务的时间购买即可。

Java设计模式学习记录-策略模式的更多相关文章

  1. Java设计模式学习记录-状态模式

    前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使 ...

  2. Java设计模式学习记录-模板方法模式

    前言 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 模板方法模式 概念介绍 模板方法模式,其实是很好理解的,具体 ...

  3. Java设计模式学习记录-备忘录模式

    前言 这次要介绍的是备忘录模式,也是行为模式的一种 .现在人们的智能手机上都会有备忘录这样一个功能,大家也都会用,就是为了记住某件事情,防止以后自己忘记了.那么备忘录模式又是什么样子的呢?是不是和手机 ...

  4. Java设计模式学习记录-迭代器模式

    前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...

  5. Java设计模式学习记录-解释器模式

    前言 这次介绍另一个行为模式,解释器模式,都说解释器模式用的少,其实只是我们在日常的开发中用的少,但是一些开源框架中还是能见到它的影子,例如:spring的spEL表达式在解析时就用到了解释器模式,以 ...

  6. Java设计模式学习记录-命令模式

    前言 这次要介绍的是命令模式,这也是一种行为型模式.最近反正没有面试机会我就写博客呗,该投的简历都投了.然后就继续看书,其实看书也会给自己带来成就感,原来以前不明白的东西,书上已经给彻底的介绍清楚了, ...

  7. Java设计模式学习记录-外观模式

    前言 这次要介绍的是外观模式(也称为门面模式),外观模式也属于结构型模式,其实外观模式还是非常好理解的,简单的来讲就是将多个复杂的业务封装成一个方法,在调用此方法时可以不必关系具体执行了哪些业务,而只 ...

  8. Java设计模式学习记录-桥接模式

    前言 这次介绍结构型设计模式中的第二种模式,桥接模式. 使用桥接模式的目的就是为了解耦,松散的耦合更利于扩展,但是会增加相应的代码量和设计难度. 桥接模式 桥接模式是为了将抽象化与实现化解耦,让二者可 ...

  9. Java设计模式学习记录-代理模式

    代理模式 代理模式是常见设计模式的一种,代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...

随机推荐

  1. html 语法

    p: 源代码中包含多行,但是浏览器会忽略多行 <br />产生折行效果 h1:居中用样式实现 :水平线,有的很像border-top/bottom,或许用 实现更好 pre: 预格式化的文 ...

  2. TryEnterCriticalSection___Delphi

    VOID EnterCriticalSection:非阻塞函数.将当前线程对指定临界区的引用计数减1:在使用计数变为零时,另一等待此临界区的一个线程将被唤醒. BOOL TryEnterCritica ...

  3. 4.css基础

    1 Css概念 CSS 指层叠样式表 (Cascading Style Sheets)(级联样式表) Css是用来美化html标签的,相当于页面化妆. ◆样式表书写位置 2选择器 2.1 写法 选择器 ...

  4. OpencvSharp 在WPF的Image控件中显示图像

    1.安装OpencvSharp 我使用的是VS2013 社区版,安装OpencvSharp3.0 在线安装方法:进入Tools,打开NuGet的包管理器 搜索Opencv 安装之后就可以使用,无需再做 ...

  5. Windows核心编程:第5章 作业

    Github https://github.com/gongluck/Windows-Core-Program.git //第5章 作业.cpp: 定义应用程序的入口点. // #include &q ...

  6. #loj3090 [BJOI2019] 勘破神机

    简单线性代数练习题 首先翻开具体数学生成函数一章,可以发现\(F(n),G(n)\)满足以下递推式 \[F(n)=F(n-1)+F(n-2),F(0)=1,F(1)=1\] \[G(n)=4G(n-2 ...

  7. jzoj4229

    按照題意暴力模擬即可 #include<bits/stdc++.h> using namespace std; int m; typedef long long ll; ll a1,q,n ...

  8. 如何给wp(Windows phone)中搜索关键字加亮?

    问题来源 最近在群里看到群友讨论在wp中有个搜索功能,要求搜索关键字在搜索结果内容中加亮(即加颜色),由于wp中没有自带这样的控件,于是大家各抒自见,有人说用第三方控件,有人说用richtextbox ...

  9. html和css入门

    html 单机软件:软件程序和数据都存储在客户端 界面:Tk.PyQt.wxPython库C/S(Client/Server)架构软件:软件程序和数据一部分存在客户端,一部分存在服务器端 界面:Tk. ...

  10. iOS-xcconfig环境变量那些事(配置环境的配置)

    前言 在配置宏定义参数时,会发现一个问题,在需要临时修改或者测试一些数据时,修改宏,如果不修改,就多写一个,注释掉原来的,然后测试后,再换回来,当然了,如果一两个宏,可以这样,但是,如果每次改的比较多 ...