案例突破——再探策略模式
再探设计模式
一、背景介绍
在做项目重构的过程中,发现对于主题讨论中,针对于学生评论/回复的内容的按照评论/回复日期排序、按照评论数量排序、按照点赞次数排序可以使用策略模式进行优化。
二、 思路方案
- 策略模式基本概念
- 策略模式类图
- 策略模式基本代码
- 策略模式还可以进行优化的地方
- 对策略模式进行优化
三、过程
1. 策略模式基本概念
定义:定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化不会影响到使用算法的客户。
2. 策略模式类图
3. 策略模式基本代码
策略类
package com.wangwei.strategypattern.normal;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : ConcreteStrategy
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:34]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:34]
* @updateRemark : [描述说明本次修改内容]
*/
public class ConcreteStrategyA implements IStrategy{
public void AlgorithmInterface(){
System.out.println("算法A实现");
}
}
package com.wangwei.strategypattern.normal;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : ConcreteStrategy
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:34]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:34]
* @updateRemark : [描述说明本次修改内容]
*/
public class ConcreteStrategyB implements IStrategy{
public void AlgorithmInterface(){
System.out.println("算法B实现");
}
}
package com.wangwei.strategypattern.normal;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : ConcreteStrategy
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:34]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:34]
* @updateRemark : [描述说明本次修改内容]
*/
public class ConcreteStrategyC implements IStrategy{
public void AlgorithmInterface(){
System.out.println("算法C实现");
}
}
抽象策略类
package com.wangwei.strategypattern.normal;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : IStrategy
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:37]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:37]
* @updateRemark : [描述说明本次修改内容]
*/
public interface IStrategy {
void AlgorithmInterface();
}
Context类
package com.wangwei.strategypattern.normal;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : Context
* @description : [公共上下文]
* @createTime : [2023/9/7 10:38]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:38]
* @updateRemark : [描述说明本次修改内容]
*/
public class Context {
IStrategy iStrategy=null;
public Context(IStrategy iStrategy) {
this.iStrategy = iStrategy;
}
public void ContextInterface(){
iStrategy.AlgorithmInterface();
}
}
客户端
package com.wangwei.strategypattern.normal;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : Client
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:40]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:40]
* @updateRemark : [描述说明本次修改内容]
*/
public class Client {
public static void main(String[] args) {
Context context=null;
context= new Context(new ConcreteStrategyA());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
}
}
4. 策略模式还可以进行优化的地方
当我们需要增加新的策略的时候,是需要修改客户端的代码,那么对于客户端来说是不符合开闭原则的。
5. 对策略模式的优化(配置文件+反射)
package com.wangwei.strategypattern.better;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : ConcreteStrategy
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:34]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:34]
* @updateRemark : [描述说明本次修改内容]
*/
public class ConcreteStrategyA implements IStrategy {
public void AlgorithmInterface(){
System.out.println("算法A实现");
}
}
package com.wangwei.strategypattern.better;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : ConcreteStrategy
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:34]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:34]
* @updateRemark : [描述说明本次修改内容]
*/
public class ConcreteStrategyB implements IStrategy {
public void AlgorithmInterface(){
System.out.println("算法B实现");
}
}
package com.wangwei.strategypattern.better;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : ConcreteStrategy
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:34]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:34]
* @updateRemark : [描述说明本次修改内容]
*/
public class ConcreteStrategyC implements IStrategy {
public void AlgorithmInterface(){
System.out.println("算法C实现");
}
}
package com.wangwei.strategypattern.better;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : Context
* @description : [公共上下文]
* @createTime : [2023/9/7 10:38]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:38]
* @updateRemark : [描述说明本次修改内容]
*/
public class Context {
static Map<String,String> config = new HashMap<>();
static Map<String,IStrategy> configBean = new HashMap<>();
//提前读取配置文件中的策略,并提前准备好已有的策略对象
static {
InputStream inputStream = Context.class.getResourceAsStream("/config.properties");
Properties properties = new Properties();
try {
properties.load(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
String strategyType = properties.getProperty("strategyType");
String[] strs = strategyType.split(",");
for (String string : strs) {
String key = string.split(":")[0];
String value = string.split(":")[1];
// 去掉头部空格
String key1 = key.trim();
String value1 = value.trim();
config.put(key1, value1);
}
//提前准备好已有的策略对象
for (Map.Entry<String,String> entry:config.entrySet()) {
Class strategyClass ;
try {
strategyClass = Class.forName(entry.getValue());
configBean.put(entry.getKey(),(IStrategy) strategyClass.getConstructor().newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
IStrategy iStrategy;
public Context(String type) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
if(configBean.containsKey(type)){
this.iStrategy = configBean.get(type);
}else {
Class strategyClass = Class.forName(config.get(type));
this.iStrategy = (IStrategy)strategyClass.getConstructor().newInstance();
}
}
public void ContextInterface(){
iStrategy.AlgorithmInterface();
}
}
package com.wangwei.strategypattern.better;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : IStrategy
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:37]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:37]
* @updateRemark : [描述说明本次修改内容]
*/
public interface IStrategy {
void AlgorithmInterface();
}
package com.wangwei.strategypattern.better;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
/**
* @author : [WangWei]
* @version : [v1.0]
* @className : Client
* @description : [描述说明该类的功能]
* @createTime : [2023/9/7 10:40]
* @updateUser : [WangWei]
* @updateTime : [2023/9/7 10:40]
* @updateRemark : [描述说明本次修改内容]
*/
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException {
/*
1.前端通过下拉框选择不同的类型
2.类型是从配置文件中读取的
*/
Context context;
context= new Context("strategyA");
context.ContextInterface();
context = new Context("strategyB");
context.ContextInterface();
context = new Context("strategyC");
context.ContextInterface();
}
}
四、总结
-
优点:配置文件+反射的方式,符合开闭原则。用户可以在不修改原有代码的基础上选择算法,也可以灵活的增加新的算法。
-
缺点:无法同时在客户端使用多个策略类。
-
关键点:都是对通一份数据,根据不同的算法进行处理。
-
什么时候使用策略模式:一个系统需要动态地在几种算法中选择一种。
五、升华
- 学习是一个反复的过程:通过项目切实的需求来结合具体的设计模式,在反过来在此基础上优化设计模式。