常用设计模式系列(十六)---策略模式
第一节
前言
hello各位好,小编由于最近上了年纪,总是感觉到自己困意频繁袭击,有一点低产,不能够达到一天一更的频率,但是后期可以使用两三天一更的频率,来保证文章的质量。最近小编身边也有许多朋友因为压力大而生病,大家应该注重身体健康,毕竟身体是革命的本钱,切勿劳累过度,伤身伤财。

今天我带大家唠唠对象行为型模式第一章节---策略模式, 策略一词,可以理解为,当我们去完成一个任务时,应对不同的场景、不同的困难,可以使用自己内心准备好的应急方案,提供这个方案的这个过程,就是策略模式。
第二节
策略模式
策略模式(Strategy Pattern)概念:定义一系列算法,并且将每个算法封装起来,并让他们可以互相替换,策略模式可以让算法独立于使用它的客户而变化。
策略模式组成:

个人理解:
当去完成或者达到一个目标时,这个目标就是我们的最终结果,实现这个目标的方案(抽像名词)就是抽像策略,不管用什么方案,我要的是这个结果,方案一、方案二不同的实现方式,称之为具体策略,我们在实现这个目标的过程中遇到的突发情况去选择不同的方案(自己选择方案,即客户端选择方案),选择好以后,根据方案去完成的这个过程,就可以理解为环境类。
场景举例:
我是小杨,前段时间公司安排我去北京出差,我看了下公司的报销政策,可以自行选择出差使用的交通工具,那这些交通方式都能够达到目的地,交通方式一词它就是抽象策略。而汽车、火车、高铁、飞机就是对应的具体策略。因为小编比较穷,但是又不想花费太多时间在路上,我就选择了高铁(毕竟飞机票买不起,汽车和火车又不想坐),我打开购票软件,选择高铁后,打车去高铁站的这个过程就是环境类,当我坐上高铁,抵达北京,整个结果达成,则整个策略模式结束。
第三节
案例举例及分析:
在生活中,坐公交、坐地铁是市民通行的几种常见方式,但是针对不同的人群,办理公交卡(使用现金无折扣),拥有着不同的优惠政策
1.学生卡享受8折优惠
2.老人卡享受5折优惠
3.市民卡享受85折优惠 如果后期加入不同的优惠政策,使用策略模式则可以设计并更好的扩展优惠政策。
根据分析,可以设计出如下几个类:
1.BusTikect刷卡机类,充当环境类,用来调用不同的折扣类。
2.Discount折扣类,充当抽象策略类。
3.StudentDiscount 学生卡折扣类,充当具体策略类
4.SeniorDiscount 老人卡折扣类,充当具体策略类
5.CitizenDiscount 市民卡折扣类,充当具体策略类
UML图

代码实现
1.BusTikect刷卡机类,充当环境类,用来调用不同的折扣类。
package com.yang.strategy;
/**
* @ClassName BusTikect
* @Description 刷卡机类
* @Author IT小白架构师之路
* @Date 2021/1/22
* @Version 1.0
**/
public class BusTikect {
//票价
private double price;
//折扣类型
private Discount discount;
//构造
public BusTikect(double price,Discount discount){
this.price = price;
this.discount = discount;
}
//折扣计算
public double getPrice(){
return discount.caculate(this.price);
}
}
2.Discount折扣类,充当抽象策略类。
package com.yang.strategy;
/**
* @ClassName Discount
* @Description 折扣类
* @Author IT小白架构师之路
* @Date 2021/1/22
* @Version 1.0
**/
public interface Discount {
/**
* 计算折扣
* @param price
* @return
*/
public double caculate(double price);
}
3.StudentDiscount 学生卡折扣类,充当具体策略类
package com.yang.strategy;
/**
* @ClassName StudentDiscount
* @Description 学生折扣
* @Author IT小白架构师之路
* @Date 2021/1/22
* @Version 1.0
**/
public class StudentDiscount implements Discount{
private final double DISCOUNT = 0.8;
@Override
public double caculate(double price) {
System.out.println("学生卡:");
return this.DISCOUNT * price;
}
}
4.SeniorDiscount 老人卡折扣类,充当具体策略类
package com.yang.strategy;
/**
* @ClassName SeniorDiscount
* @Description 老人卡折扣类
* @Author IT小白架构师之路
* @Date 2021/1/22
* @Version 1.0
**/
public class SeniorDiscount implements Discount{
private final double DISCOUNT = 0.5;
@Override
public double caculate(double price) {
System.out.println("老人卡:");
return this.DISCOUNT * price;
}
}
5.CitizenDiscount 市民卡折扣类,充当具体策略类
package com.yang.strategy;
/**
* @ClassName CitizenDiscount
* @Description 市民卡折扣类
* @Author IT小白架构师之路
* @Date 2021/1/22
* @Version 1.0
**/
public class CitizenDiscount implements Discount{
private final double DISCOUNT = 0.85;
@Override
public double caculate(double price) {
System.out.println("市民卡:");
return this.DISCOUNT * price;
}
}
6.编写客户端测试
package com.yang.strategy;
/**
* @ClassName Client
* @Description 注释
* @Author IT小白架构师之路
* @Date 2021/1/22
* @Version 1.0
**/
public class Client {
public static void main(String[] args) {
//长途公交价格
double price = 5;
System.out.println("-------------车来了,请按顺序刷卡上车,不要拥挤---------------");
//学生卡
Discount discount = new StudentDiscount();
//刷卡机
BusTikect busTikect = new BusTikect(price,discount);
System.out.println("折扣前价格:"+price);
//刷卡
double priceNew = busTikect.getPrice();
System.out.println("折扣后价格:"+priceNew);
System.out.println("----------------------------");
//老人卡
discount = new SeniorDiscount();
//刷卡机
busTikect = new BusTikect(price,discount);
System.out.println("折扣前价格:"+price);
//刷卡
priceNew = busTikect.getPrice();
System.out.println("折扣后价格:"+priceNew);
System.out.println("----------------------------");
//市民卡
discount = new CitizenDiscount();
//刷卡机
busTikect = new BusTikect(price,discount);
System.out.println("折扣前价格:"+price);
//刷卡
priceNew = busTikect.getPrice();
System.out.println("折扣后价格:"+priceNew);
System.out.println("------------车开了,请不要扶靠车门,谨防夹伤----------------");
}
}
7.测试结果如下
-------------车来了,请按顺序刷卡上车,不要拥挤---------------
折扣前价格:5.0
学生卡:折扣后价格:4.0
----------------------------
折扣前价格:5.0
老人卡:折扣后价格:2.5
----------------------------
折扣前价格:5.0
市民卡:折扣后价格:4.25
------------车开了,请不要扶靠车门,谨防夹伤----------------
第四节
策略模式与工厂模式的区别
当看到策略模式的组成时,大家可能会想,这不就是工厂模式吗,但是这是两个不同的模式,只是结构上很相似
1.用途不一样
(1)工厂是创建型模式,它的作用就是创建对象;
(2)策略是行为型模式,它的作用是让一个对象在许多行为中选择一种行为;
2.关注点不一样
(1)一个关注对象创建过程
(2)一个关注行为的封装
3.解决不同的问题
(1)工厂模式是创建型的设计模式,它接受指令,创建出符合要求的实例;它主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用客户无关。主要应用在多数据库选择,类库文件加载等。
(2)策略模式是为了解决的是策略的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。
4.工厂相当于黑盒子,策略相当于白盒子。
举例说明
有一天晚上,你跟你的室友特别想吃麻辣拌,你到附近饭店,跟老板说要一份麻辣拌,你也不关注这个过程,老板做好吃就成了,用户不需要关心过程得到麻辣拌,这就是工厂模式。
但是你的室友说,我喜欢按照自己的比例去做,然后他按照自己的要求,多加肉块,多要辣椒,土豆煮的脆一点等等要求,他关注的是这个过程,最后吃到了麻辣拌,这个过程就是策略模式,它关注过程,自主选择过程来得到结果。
第五节
优缺点及适用场景
优点
1.策略模式可以在不修改原有系统源码的基础选择新的算法或者行为,可以灵活的增加新的算法或者行为
2.策略模式解决了继承模式下:每个子类提供不同的算法,此时算法的使用和算法的声明放在了一起,此时解决了不符合单一职责的情况
3.使用策略模式可以减少多重条件选择,更易维护
4.策略模式抽象出来的代码放在了策略类中,不同的环境类都可以复用这些策略类。
缺点
1.客户端需要知道全部有多少种策略类,来去选择,对客户端的要求高一点。
2.策略模式会造成系统产生很多的具体策略类,当需求变化就要增加新的具体策略类
3.无法同时使用多个策略类,每次只能使用一个策略类,而无法使用两个策略类共同完成
适用场景
1.一个系统需要设计几种算法供开发者选择时,可以封装到一个个的具体策略类中,在某段程序使用时,使用统一的接口调用即可。
2.当系统中使用了多重条件选择语句时,代码可使用策略类进行优化,把行为转移到对应的具体策略类。
3.不希望使用方知道复杂的、与算法相关的数据结构式,在具体策略类封装相关的数据结构,提高算法的保密性和安全性。
扫描二维码
关注我吧
IT小白架构师之路
