● 避免冗长的if,else判断或switch分支判断
● 提供框架的拓展点
定义一族算法类,将每个算法分别封装起来,让它们可以互相替换
策略模式主要包含以下角色:
● 策略接口(Strategy):定义所有支持的算法的公共接口。客户端使用这个接口与具体策略进行交互
● 具体策略(Concrete Strategy):实现策略接口的具体策略类。这些类封装了实际的算法逻辑。
● 上下文(Context):持有一个策略对象,用于与客户端进行交互。
让我们以一个简单的例子来说明策略模式:假设我们要实现一个计算器,支持加法、 减法和乘法运算。我们可以使用策略模式将各种运算独立为不同的策略,并让客户端根据需要选择和使用不同的策略。
package com.hillky.desgin_learn.category;
public interface Operation {
double execute(double num1,double num2);
}
package com.hillky.desgin_learn.category;
public class Addition implements Operation{
@Override
public double execute(double num1, double num2) {
return num1+num2;
}
}
package com.hillky.desgin_learn.category;
public class Subtraction implements Operation{
@Override
public double execute(double num1, double num2) {
return num1-num2;
}
}
package com.hillky.desgin_learn.category;
public class Multiplication implements Operation{
@Override
public double execute(double num1, double num2) {
return num1*num2;
}
}
package com.hillky.desgin_learn.category;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class Calculator {
private Operation operation;
public Calculator(Operation operation) {
this.operation = operation;
}
public double executeOperation(double num1,double num2){
return operation.execute(num1,num2);
}
}
package com.hillky.desgin_learn.category;
public class Client {
public static void main(String[] args) {
Calculator calculator = new Calculator();
calculator.setOperation(new Addition());
System.out.println("10 + 5 = " + calculator.executeOperation(10, 5));
calculator.setOperation(new Subtraction());
System.out.println("10 - 5 = " + calculator.executeOperation(10, 5));
calculator.setOperation(new Multiplication());
System.out.println("10 * 5 = " + calculator.executeOperation(10,5));
}
}
优点:
● 提高代码的可维护性和可扩展性。
● 符合开闭原则(对增加开,对修改关闭)
● 避免使用多重条件判断
缺点
● 客户端需要了解所有的策略
● 增加了类的数量。策略模式会导致程序中具体策略类的数量增加,这可能会导致代码的复杂性增加。
场景:是一段代码屎山,需求是根据不同的报文格式解析报文,下面说一下对这顿屎山的优化
package com.hillky.desgin_learn.category.messageParse;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Message {
private String content;
private String type;
}
package com.hillky.desgin_learn.category.messageParse;
public class MessageParser {
public void parseMessage(Message message) {
String messageType = message.getType();
if ("XML".equalsIgnoreCase(messageType)) {
// 解析 XML 报文
System.out.println("解析 XML 报文: " + message.getContent());
} else if ("JSON".equalsIgnoreCase(messageType)) {
// 解析 JSON 报文
System.out.println("解析 JSON 报文: " + message.getContent());
} else if ("CSV".equalsIgnoreCase(messageType)) {
// 解析 CSV 报文
System.out.println("解析 CSV 报文: " + message.getContent());
} else {
throw new IllegalArgumentException("未知的报文类型: " + messageType);
}
}
}
package com.hillky.desgin_learn.category.messageParse;
public interface MessageParserStrategy {
// 解析报文内容的方法,输入一个 Message 对象,无返回值
void parse(Message message);
}
package com.hillky.desgin_learn.category.messageParse;
// XML 报文解析策略
public class XmlMessageParserStrategy implements MessageParserStrategy{
@Override
public void parse(Message message) {
System.out.println("解析 XML 报文: " + message.getContent());
}
}
package com.hillky.desgin_learn.category.messageParse;
// JSON 报文解析策略
public class JsonMessageParserStrategy implements MessageParserStrategy {
@Override
public void parse(Message message) {
System.out.println("解析 JSON报文: " + message.getContent());
}
}
package com.hillky.desgin_learn.category.messageParse;
// CSV 报文解析策略
public class CsvMessageParserStrategy implements MessageParserStrategy {
@Override
public void parse(Message message) {
System.out.println("解析 CSV报文: " + message.getContent());
}
}
package com.hillky.desgin_learn.category.messageParse;
public class Client {
public static void main(String[] args) {
MessageParserContext parserContext = new MessageParserContext();
// 使用 XML 报文解析策略
parserContext.setStrategy(new XmlMessageParserStrategy());
parserContext.parseMessage(new Message("XML", "这是一个 XML 报文 "));
// 使用 JSON 报文解析策略
parserContext.setStrategy(new JsonMessageParserStrategy());
parserContext.parseMessage(new Message("JSON", "{\"message\": \"这是一个 JSON 报文\"}"));
// 使用 CSV 报文解析策略
parserContext.setStrategy(new CsvMessageParserStrategy());
parserContext.parseMessage(new Message("CSV", "这是一个,CSV,报文"));
}
}
我们可以将策略模式与工厂模式结合,以便根据不同的消息类型自动匹配不同的解析策略。下面是如何实现这个优化的:
package com.hillky.desgin_learn.category.messageParse;
import java.util.HashMap;
import java.util.Map;
public class MessageParserStrategyFactory {
private static final Map<String, MessageParserStrategy> strategies = new
HashMap<>();
static {
strategies.put("XML", new XmlMessageParserStrategy());
strategies.put("JSON", new JsonMessageParserStrategy());
strategies.put("CSV", new CsvMessageParserStrategy());
}
public MessageParserStrategy getStrategy(String messageType){
MessageParserStrategy strategy =
strategies.get(messageType.toUpperCase());
if (strategy == null) {
throw new IllegalArgumentException("未知的报文类型: " + messageType);
}
return strategy;
}
}
package com.hillky.desgin_learn.category.messageParse;
import lombok.Data;
@Data
public class MessageParserContext {
private MessageParserStrategy strategy;
// 设置报文解析策略
public void setStrategy(MessageParserStrategy strategy) {
this.strategy = strategy;
}
// 根据策略解析报文
public void parseMessage(Message message) {
// strategy.parse(message);
MessageParserStrategyFactory.getStrategy(message.getType()).parse(message);
}
}
package com.hillky.desgin_learn.category.messageParse;
public class Client {
public static void main(String[] args) {
MessageParserContext parserContext = new MessageParserContext();
// 自动使用 XML 报文解析策略
parserContext.parseMessage(new Message("XML", "这是一个 XML 报 文 "));
// 自动使用 JSON 报文解析策略
parserContext.parseMessage(new Message("JSON", "{\"message\": \"这是一 个 JSON 报文\"}"));
// 自动使用 CSV 报文解析策略
parserContext.parseMessage(new Message("CSV", "这是一个,CSV,报文"));
}
}
通过将策略模式与工厂模式结合,我们优化了报文解析过程。这样的代码更容易扩展 和维护,因为我们可以通过在工厂类中添加新的解析策略来轻松地支持新的报文类型。
下面我们以 java.util.Comparator 接口为例,展示策略模式在JDK中的应用。
我们可以使用策略模式,通过实现 Comparator 接口,为不同的排序需求提供
不同的比较策略。
package com.hillky.desgin_learn.category.jdk;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Student {
private String name;
private int age;
private double score;
}
package com.hillky.desgin_learn.category.jdk;
import java.util.Comparator;
public class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
}
package com.hillky.desgin_learn.category.jdk;
import java.util.Comparator;
public class ScoreComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return (int) (o1.getScore()-o2.getScore());
}
}
package com.hillky.desgin_learn.category.jdk;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Client {
public static void main(String[] args) {
// 创建一个Student对象的列表
List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 20, 90.0));
students.add(new Student("Bob", 18, 85.0));
students.add(new Student("Charlie", 22, 88.0));
// 使用年龄比较策略进行排序
Collections.sort(students, new AgeComparator());
System.out.println("按年龄排序: " + students);
// 使用成绩比较策略进行排序
Collections.sort(students, new ScoreComparator());
System.out.println("按成绩排序: " + students);
}
}