【设计模式】策略模式

引例


方案一

说明:

  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);
	}
}

练习二


相关推荐
一棵开花的树,枝芽无限靠近你6 分钟前
【PPTist】添加PPT模版
前端·学习·编辑器·html
陈王卜9 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、9 分钟前
Spring Boot 注解
java·spring boot
java亮小白199714 分钟前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF20 分钟前
java Queue 详解
java·队列
VertexGeek25 分钟前
Rust学习(八):异常处理和宏编程:
学习·算法·rust
武子康42 分钟前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康44 分钟前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
苏-言1 小时前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
界面开发小八哥1 小时前
更高效的Java 23开发,IntelliJ IDEA助力全面升级
java·开发语言·ide·intellij-idea·开发工具