设计模式系列之策略模式(Strategy Pattern)
- 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
- 主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
- 何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
- 如何解决:将这些算法封装成一个一个的类,任意地替换。
- 关键代码:实现同一个接口。
- 应用实例:
- 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
- 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
- 3、JAVA AWT 中的 LayoutManager。
- 优点:
- 1、算法可以自由切换。
- 2、避免使用多重条件判断。
- 3、扩展性良好。
- 缺点:
- 1、策略类会增多。
- 2、所有策略类都需要对外暴露。
- 使用场景:
- 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 2、一个系统需要动态地在几种算法中选择一种。
- 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
案例说明
用户到超市购买东西不同的会员等级,不同的折扣
等级 | 折扣 |
---|---|
NormalUser | 100% |
VIPUser | 90% |
SuperUser | 80% |
GlodUser | 70% |
通过实现CalPrice实现不同的计算方式,在User代码中设定总价和计算折扣的方式即可.
代码实现
普通实现
public class Demo {
public static void main(String[] args) {
float sumPrice = 100;
if(sumPrice > 100){
sumPrice = sumPrice * 0.9f;
}else if(sumPrice > 60){
sumPrice = sumPrice * 0.8f;
}else if(sumPrice > 30){
sumPrice = sumPrice * 0.7f;
}
System.out.println("计算之后的价格是:" + sumPrice);
// 加入需求更改为满500元打5折???? 代码是不是越来越复杂?
}
}
接口
package com.zhoutao123.design.pattern.Strategy.calprice;
public interface CalPrice {
Float calPrice(Float sumPrice);
}
不同的实现方法
- 普通会员
package com.zhoutao123.design.pattern.Strategy.calprice;
public class NormalUserCalPrice implements CalPrice {
@Override
public Float calPrice(Float sumPrice) {
System.out.println(String.format("当前计算总价:%f 折扣:%f",sumPrice,1.0f));
return sumPrice;
}
}
- VIP 会员
package com.zhoutao123.design.pattern.Strategy.calprice;
public class VIPUserCalPrice implements CalPrice {
@Override
public Float calPrice(Float sumPrice) {
System.out.println(String.format("当前计算总价:%f 折扣:%f",sumPrice,0.9f));
return sumPrice * 0.9f;
}
}
- SuperVIP会员
package com.zhoutao123.design.pattern.Strategy.calprice;
import com.zhoutao123.design.pattern.Strategy.calprice.CalPrice;
public class SuperUserCalPrice implements CalPrice {
@Override
public Float calPrice(Float sumPrice) {
System.out.println(String.format("当前计算总价:%f 折扣:%f",sumPrice,0.8f));
return sumPrice * 0.8f;
}
}
- GlodVIP会员
package com.zhoutao123.design.pattern.Strategy.calprice;
public class GlodUserCalPrice implements CalPrice {
@Override
public Float calPrice(Float sumPrice) {
System.out.println(String.format("当前计算总价:%f 折扣:%f",sumPrice,0.7f));
return sumPrice * 0.7f;
}
}
用户代码
package com.zhoutao123.design.pattern.Strategy;
import com.zhoutao123.design.pattern.Strategy.calprice.*;
public class User {
private float sumPrice = 0f;
// 计算的对象,注意在setSumPrice(float)会根据不同的总额设置不同的实现
private CalPrice calPrice;
public void setSumPrice(float sumPrice) {
this.sumPrice = sumPrice;
}
/**
* 设置用户的折扣计算方式
* @param
*/
public void setCalPrice(CalPrice calPrice) {
this.calPrice =calPrice;
}
/**
* 获取用户的应当付钱
* @return
*/
public float payAmount() {
return calPrice.calPrice(this.sumPrice);
}
}
测试代码
package com.zhoutao123.design.pattern.Strategy;
import com.zhoutao123.design.pattern.Strategy.calprice.GlodUserCalPrice;
import com.zhoutao123.design.pattern.Strategy.calprice.NormalUserCalPrice;
import com.zhoutao123.design.pattern.Strategy.calprice.SuperUserCalPrice;
import com.zhoutao123.design.pattern.Strategy.calprice.VIPUserCalPrice;
public class Test {
public static void main(String[] args) {
User user1 = new User();
// 设定用户的消费总额为10元,会员等级为普通会员,不大这
user1.setSumPrice(10);
user1.setCalPrice(new NormalUserCalPrice());
System.out.println("user1 = " + user1.payAmount());
// 后来用户觉得就买10元的东西不太好,于是又买了23快的东西
// 他发现自己有张VIP 的会员卡,所以他的价格为
user1.setSumPrice(33);
user1.setCalPrice(new VIPUserCalPrice());
System.out.println("user1 = " + user1.payAmount());
// 后面的故事自己想,:>
user1.setSumPrice(53.3f);
user1.setCalPrice(new SuperUserCalPrice());
System.out.println("user1 = " + user1.payAmount());
user1.setSumPrice(130000);
user1.setCalPrice(new GlodUserCalPrice());
System.out.println("user1 = " + user1.payAmount());
}
}
拓展
试想一下,假如说某一天VIP 会员机制改革了,要求满额100元才能打9折,那么我们只要修改VIP折扣计算中的代码即可,无需修改User的代码,只要修改计算方式,这样的代码看起来是不是更清爽一点.
package com.zhoutao123.design.pattern.Strategy.calprice;
public class VIPUserCalPrice implements CalPrice {
@Override
public Float calPrice(Float sumPrice) {
if(sumPrice >= 100) {
System.out.println(String.format("当前计算总价:%f 折扣:%f", sumPrice, 0.9f));
return sumPrice * 0.9f;
}else {
System.out.println(String.format("当前计算总价:%f 折扣:%f", sumPrice, 1.0f));
return sumPrice;
}
}
}
设计模式系列之策略模式(Strategy Pattern)的更多相关文章
- 设计模式(一):“穿越火线”中的“策略模式”(Strategy Pattern)
在前段时间呢陆陆续续的更新了一系列关于重构的文章.在重构我们既有的代码时,往往会用到设计模式.在之前重构系列的博客中,我们在重构时用到了“工厂模式”.“策略模式”.“状态模式”等.当然在重构时,有的地 ...
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...
- 反馈法学习设计模式(一)——策略模式Strategy Pattern
简介(Introduction) 之前学习Java8实战时,遇到一个很好的策略模式示例.便想着借着这个示例结合反馈式的方法来,学习策略设计模式,也以便后面反复琢磨学习. 首先我们通过练习,逐步写出符合 ...
- 设计模式 - 策略模式(Strategy Pattern) 具体解释
策略模式(Strategy Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版权全 ...
- HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern)
策略模式(Strategy Pattern): 定义了了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户端. 第一个设计原则:找出应用中可能需要变化之处,把他们独立 ...
- 8.6 GOF设计模式四: 策略模式… Strategy Pattern
策略模式… Strategy Pattern 在POS系统中,有时需要实行价格优惠, 该如何处理? 对普通客户或新客户报全价 对老客户统一折扣5% 对大客户统一折扣10% 注:课件 ...
- 二十四种设计模式:策略模式(Strategy Pattern)
策略模式(Strategy Pattern) 介绍定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例有一个Message实体类,对它的操作有 ...
- 【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成 ...
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...
随机推荐
- [Swift]LeetCode4. 两个排序数组的中位数 | Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...
- [Swift]LeetCode733. 图像渲染 | Flood Fill
An image is represented by a 2-D array of integers, each integer representing the pixel value of the ...
- [Swift]LeetCode956. 最高的广告牌 | Tallest Billboard
You are installing a billboard and want it to have the largest height. The billboard will have two ...
- 基于IPV6的数据包分析(更新拓扑加入了linux主机和抓取133icmp包)(第十三组)
1.拓扑图 2.配置ipv6地址,在拓扑图上对应位置标有对应网段,所在网段的端口按照网段配置,下图以r4为例 3.配置路由表,由于静态路由还要敲ip很麻烦所以使用ospf协议,下图为ospf配置以r5 ...
- 作为程序员必须掌握的Java虚拟机中的22个重难点
Java虚拟机一直是比较重要的知识点,是Java高级开发必会的.本文为你总结了关于JVM的22个重点.难点,图文并茂的向你展示和JVM有关的重点知识.全文共7000字左右. 概念 虚拟机:指以软件的方 ...
- Visual Studio 2017 怎么将自动生成属性设置为旧版格式
工具:Visual Studio 2017 1.点击工具,进入选项 2.选项窗口左侧找到C#--代码样式,点击 3.找到表达式首选项中:使用属性的表达式主体.使用索引器的表达式主体和使用访问器的表达式 ...
- bootcamp分区_BOOTCAMP 删除分区失败
mac 装了双系统,Mac OS X 分配的内存太少了,导致使用卡顿,要删掉windows系统. 在删除windows的时候出现 “您的磁盘不能恢复为单一的分区” 解决方案: 1.重启Mac,并按下 ...
- mysql 架构篇系列 4 复制架构一主一从搭建(半同步复制)
一.概述 在mysql 5.5之前,mysql 的复制是异步操作,主库和从库的数据之间存在一定的延时,这样存在一个隐患:当主库上写入一个事务并提交成功,而从库尚未得到主库推送的Binlog日志时,主库 ...
- 从锅炉工到AI专家(3)
剖析第一个例子 学习<机器学习>,很多IT高手是直接去翻看TensorFlow文档,但碰壁的很多.究其原因,TensorFlow的文档跨度太大了,它首先假设你已经对"机器学习&q ...
- 设计模式总结篇系列:抽象工厂模式(Abstract Factory)
在上一篇的工厂方法模式中,通过一个公用的类对其他具有相同特性(实现相同接口或继承同一父类)的类的对象进行创建.随之带来的问题在于:当新定义了一个具有相同特性的类时,需要修改工厂类.这与设计模式中的开闭 ...