Java设计模式之策略模式

时间:2022-12-19 13:58:27


Java设计模式之策略模式

一、策略模式简介

策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。

Java设计模式之策略模式

二、策略模式使用场景

2.1. 策略模式组成

这个模式涉及到三个角色:

  • 环境(​​Context​​​)角色:持有一个​​Strategy​​的引用。
  • 抽象策略(​​Strategy​​)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口
  • 具体策略(​​ConcreteStrategy​​)角色:包装了相关的算法或行为。
2.2. 使用场景
  • 去掉硬编码,可以用策略模式进行优化;(例如:不同用户不同的结算方法)
  • 动态切换数据源; (例如:可以动态切换​​Mysql​​​或者 ​​oracle​​ 数据库)
  • 其他的具体看业务或者架构去实际使用吧。说白了就是对多个​​if...else​​的优化。
2.3. 优缺点

优点: 替换继承关系,避免使用多重条件转移语句。

缺点: 客户端必须知道所有策略类,并自行决定使用哪一种策略类。如果算法较多,则会造成很多的策略类。

三、策略模式实现

抽象策略角色:

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName Strategy.java
* @Description 四则运算策略接口
* @createTime 2019年11月15日
*/
public interface Strategy {

/**
* 操作
* @param a
* @param b
* @return
*/
Integer operator(Integer a, Integer b);

}

具体四则运算实现:

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName AddStrategy.java
* @Description 加法操作策略
*/
public class AddStrategy implements Strategy {

@Override
public Integer operator(Integer a, Integer b) {
return a + b;
}
}

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName DivStrategy.java
* @Description 除法操作策略
*/
public class DivStrategy implements Strategy {

@Override
public Integer operator(Integer a, Integer b) {
return a / b;
}
}

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName MulStrategy.java
* @Description 乘法操作策略
*/
public class MulStrategy implements Strategy {

@Override
public Integer operator(Integer a, Integer b) {
return a * b;
}
}

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName SubStrategy.java
* @Description 减法操作策略
*/
public class SubStrategy implements Strategy {

@Override
public Integer operator(Integer a, Integer b) {
return a - b;
}
}

上下文类 :

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName Context.java
* @Description 上下文类
*/
public class Context {

private Strategy strategy;

public Context(Strategy strategy) {
this.strategy = strategy;
}

public Integer getResult(Integer a, Integer b) {
return strategy.operator(a, b);
}

}

测试类:

public class Main {

public static void main(String[] args) {
Integer a = 10, b = 90;
Integer res = new Context(new AddStrategy()).getResult(a ,b);
System.out.println("a (" + a + ") + b (" + b + ") = " + res);
}

}

Java设计模式之策略模式

四、策略模式与工厂模式的区别

4.1. 相同之处:
  1. 都有一个抽象类或者公共接口,并且在抽象类中需要顶一个抽象方法;
  2. 总体来说,模式结构上差不多。
4.2. 不同之处
  1. 工厂模式主要使用来创建对象(创建型模式,关注对象创建),通过不同的条件创建对象;
  2. 策略模式主要是实现的封装(同一个对象的不同行为,主要关注行为的选择),算法不同,需要增加子类进行实现;
  3. 策略模式需要有一个上下文类,通过组合方式(不是继承)获取子类,并且提供统一的客户端接口。

五、策略模式和工厂模式整合

只需要修改上下文类:

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName Context.java
* @Description TODO
*/
public class Context {

private Strategy strategy;

// 整合和工厂模式创建实现类
public Context(Class clazz) {
try {
this.strategy = (Strategy) Class.forName(clazz.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
}

public Integer getResult(Integer a, Integer b) {
return strategy.operator(a, b);
}

}

测试类:

public class Main {

public static void main(String[] args) {
Integer a = 10, b = 90;
Integer res = new Context(new AddStrategy()).getResult(a ,b);
System.out.println("a (" + a + ") + b (" + b + ") = " + res);
}

}

Java设计模式之策略模式

六、进阶:策略枚举

在设计模式之禅中还有一个策略枚举的方法可以实现。其实很简单,简单介绍下,我们还是对上面的那个四则运算的策略方法进行修改。

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName StrategyEnum.java
* @Description 策略枚举
*/
public enum StrategyEnum {
/** 加法 */
ADD("+") {
@Override
public Integer operator(Integer a, Integer b) {
return a + b;
}
},
/** 减法 */
SUB("-") {
@Override
public Integer operator(Integer a, Integer b) {
return a - b;
}
},
/** 除法 */
DIV("/") {
@Override
public Integer operator(Integer a, Integer b) {
return a / b;
}
},
/** 乘法 */
MUL("*") {
@Override
public Integer operator(Integer a, Integer b) {
return a * b;
}
}
;
private String key;

StrategyEnum(String key) {
this.key = key;
}

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}

public abstract Integer operator(Integer a, Integer b);

}

测试:

public class Main {
public static void main(String[] args) {
System.out.println(StrategyEnum.ADD.operator(2, 5));
System.out.println(StrategyEnum.SUB.operator(2, 5));
System.out.println(StrategyEnum.DIV.operator(2, 5));
System.out.println(StrategyEnum.MUL.operator(2, 5));
}
}

七、总结

设计模式关键,还是在实际代码中的使用体验,在完成日常开发的过程中,对自己写的代码想想是不是还有优化空间,力求写出完美的代码,一直在学习的路上,一起加油!

最后欢迎关注下公众号

Java设计模式之策略模式