【设计模式】策略模式

引例


方案一

说明:

  1. 不满足OCP,添加新的排序算法或修改某个已有排序算法需要重新编译整个类
  2. 可复用性差,Sorting类不可被直接复用

方案二

将客户类和算法类分开

说明:Sorting类可复用,但Sorting类仍不满足OCP
方案三

分离变化点:排序算法内部逻辑可能变化,排序算法个数可能变化,于是做成层次类,实现一个抽象的Sort接口

说明:满足开闭原则、依赖倒置原则

Client类和算法实现类都依赖Sort抽象接口

具体使用而言,在 Client 中的 Sort 对象实例化某个具体的子类即可

还有一个问题:Client使用不同的Sort方法时可能需要进行重复的初始化、计算排序时间等与Sort层次类提供功能无关的工作
方案四

在Client和Sort层次类之间加上一个负责初始化/全局控制的类,用以协调Client和Sort层次类,即环境类Context

代码实现

java 复制代码
// Sort抽象接口
public interface Sort {
	int[] sort(int[] num);
}
java 复制代码
// 具体排序类实现
public class BubbleSort implements Sort{
@Override
	public int[] sort(int[] num) {
		int n = num.length;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n - i - 1; j++) {
				if (num[j] > num[j + 1]) {
					int temp = num[j];
					num[j] = num[j + 1];
					num[j + 1] = temp;
				}
			}
		}
		return num;
	}
}
java 复制代码
// Context环境类的实现
public class Context {
	private Sort s;
	private long startTime;
	private long endTime;
	public Context(Sort s) {
		this.s = s;
	}
	public void startExc() {
		startTime = System.currentTimeMillis();
	}
	public void endExc() {
		endTime = System.currentTimeMillis();
	}
	public long getExcTime() {
		long exeTime = 0;
		exeTime = endTime - startTime;
		return exeTime;
	}
	public int[] sortIntArray(int[] a) {
		return s.sort(a);
	}
}
java 复制代码
// Client客户端代码实现
public class Client {
	public static void main(String[] args) {
		int[] arr = {64, 34, 25, 12, 22, 11, 90};
		Sort s = new BubbleSort();
		Context con = new Context(s);
		con.startExc();
		arr = con.sortIntArray(arr);
		con.endExc();
		System.out.println(Arrays.toString(arr));
		System.out.println(con.getExcTime());
	}
}

说明:这个设计模式仍有修改空间,应该通过在Sort具体类的sort方法中直接调用con.startExc()和con.endExc() 方法,这样得到的运行时间更加准确
方案五

在Sort层次类和Context环境类之间增加一条反向依赖

理论

定义

通过将一系列实现相同功能的算法封装起来,形成层次类,是得它们可以相互替换,且算法的变化不会影响使用算法的客户
说明

对象行为模式

通用结构

使用场景

  1. 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中
  2. 一个类中以条件语句并列起来的多种行为,每个条件分支可被封装到策略类中

课后练习

练习一

设计思路一:使用策略工厂的思路,DiscountStrategy作为抽象接口下接具体的discount策略做成一个打折策略层次类,DiscountStrategyFactory作为环境类,OrderService作为Client调用对应DiscountStrategyFactory再使用对应的打折策略

DiscountStrategyFactory实现代码:

java 复制代码
public class DiscountStrategyFactory {
	private static final Map<OrderType, DiscountStrategy> strategies =  new HashMap<OrderType, DiscountStrategy>();
	static {
	strategies.put(OrderType.NORMAL, new NormalDiscountStrateg());
	strategies.put(OrderType.GROUPON, new GrouponDiscountStrategy());
	strategies.put(OrderType.PROMOTION, new PromotionDiscountStrategy());
	}
	public static DiscountStrategy getDiscountStrategy(OrderType type) {
		return strategies.get(type);
	}
}

练习二


相关推荐
机智的叉烧17 分钟前
前沿重器[57] | sigir24:大模型推荐系统的文本ID对齐学习
人工智能·学习·机器学习
路在脚下@1 小时前
spring boot的配置文件属性注入到类的静态属性
java·spring boot·sql
森屿Serien1 小时前
Spring Boot常用注解
java·spring boot·后端
Damon_X1 小时前
桥接模式(Bridge Pattern)
设计模式·桥接模式
量子-Alex1 小时前
【多模态聚类】用于无标记视频自监督学习的多模态聚类网络
学习·音视频·聚类
吉大一菜鸡1 小时前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
苹果醋32 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader2 小时前
深入解析 Apache APISIX
java·apache
菠萝蚊鸭3 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪3 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word