Java设计模式 -- 策略模式
================
[策略模式具有相对稳定的形式,如“避实就虚”、“出奇制胜”等。一定的策略模式,既可应用于战略决策,也可应用于战术决策;既可实施于大系统的全局性行动,也可实施于大系统的局部性行动。](http://cxyroad.com/ "https://baike.baidu.com/item/%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F/646307")
策略模式定义
背景
在软件系统开发中,有许多算法可以实现某一功能,如查找、排序等,一种常见的方法是 硬编码(Hard Coding)。
例如:
- 将这些算法直接写到一个类中,提供调用方法。
- 将这些算法封装在一个统一的方法中,用if…else条件判断。
问题:
- 这种硬编码的方式在修改或新增算法时,需要修改封装算法类中的源码,这种做法会导致程序变得难以维护
- 存在大量可选的算法,会将问题变更加严重
- 不符合 开闭原则
定义
为了解决上面的问题,我们定义独立的类来封装不同的算法,让每一个类封装一个具体算法,作为一个策略。
正如如今社会的出行方式:定义一系列出行方式(自行车、汽车、火车、飞机),每个出行方式独立,且可以相互替换,出行方式独立于人。
策略模式:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。
策略模式结构分析
结构
策略模式包含如下角色:
1. Context(环境类):持有一个策略类的引用,最终给客户端调用。
2. Strategy(抽象策略类):定义所有支持的算法的公共接口。
3. ConcreteStrategy(具体策略类):实现具体算法。
实例
1. 定义策略接口(Strategy)
public interface Strategy {
void AlgorithmInterface();
}
2. 实现具体策略(ConcreteStrategy)
public class ConcreteStrategyA implements Strategy {
@Override
public void AlgorithmInterface() {
// 算法A
}
}
public class ConcreteStrategyB implements Strategy {
@Override
public void AlgorithmInterface() {
// 算法B
}
}
public class ConcreteStrategyC implements Strategy {
@Override
public void AlgorithmInterface() {
// 算法C
}
}
3. 定义环境类(Context)
public class Context {
private Strategy strategy;
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void ContextInterface() {
strategy.AlgorithmInterface();
}
}
案例
购买商品案例,用户通过客户端选择商品,创建环境类,调用环境类中的购买商品方法进行支付,根据不同的策略,选择不同的支付方式。
流程图:
类图:
代码:
抽象策略类
/**
* 抽象策略类
* 付款策略接口
*/
public interface PaymentStrategy {
double pay(double amount);
}
具体策略类
/**
* 具体策略类
* 支付宝支付策略
*/
public class AliPayStrategy implements PaymentStrategy {
@Override
public double pay(double amount) {
System.out.println("------ 支付宝支付策略 ------");
return amount;
}
}
--------------------------------------------------------------
/**
* 具体策略类
* 银行卡支付策略
*/
public class CreditCardStrategy implements PaymentStrategy {
@Override
public double pay(double amount) {
System.out.println("------ 银行卡支付策略 ------");
return amount;
}
}
--------------------------------------------------------------
/**
* 具体策略类
* 微信支付策略
*/
public class WeChatPayStrategy implements PaymentStrategy {
@Override
public double pay(double amount) {
System.out.println("------ 微信支付策略 ------");
return amount;
}
}
环境类
import java.util.ArrayList;
import java.util.List;
/**
* 环境类
* 买车
*/
public class ShoppingCart {
/**
* 购物车
*/
private List<Double> items;
/**
* 引用抽象策略类
*/
private PaymentStrategy paymentStrategy;
/**
* 初始化 购物车
*/
public ShoppingCart() {
items = new ArrayList<>();
}
/**
* 购物车中 添加商品
* @param price 商品价格
*/
public void addItem(double price) {
items.add(price);
}
/**
* set 方法注入 抽象策略类
* @param paymentStrategy 抽象策略类
*/
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
/**
* 计算购物车中 商品总价格
* @return 总价
*/
public double calculateTotal() {
double total = 0;
for (double price : items) {
total += price;
}
return total;
}
/**
* 调用具体策略类中的支付方法
* @return 购买物品总的价格
*/
public double buy() {
return paymentStrategy.pay(calculateTotal());
}
}
客户端
/**
* 客户端
*/
public class ShoppingClient {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
cart.addItem(100.0);
cart.addItem(200.0);
// 选择银行卡刷卡支付
cart.setPaymentStrategy(new CreditCardStrategy());
System.out.println("银行卡支付" + cart.buy() + "元");
// 选择微信支付
cart.setPaymentStrategy(new WeChatPayStrategy());
System.out.println("微信支付" + cart.buy() + "元");
// 选择支付宝支付
cart.setPaymentStrategy(new AliPayStrategy());
System.out.println("支付宝支付" + cart.buy() + "元");
}
}
XMLutil工具
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
public class XMLUtil
{
public static Object getBean()
{
try
{
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("Strategy.xml"));
NodeList nl = doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
}
优缺点
优点
- 提高了代码的复用性和可维护性,将算法的定义与其具体实现进行解耦。
- 可以在运行时动态替换算法,提高了程序的灵活性。
- 符合开闭原则,新增算法无需修改现有代码。
缺点
- 客户端需要知道所有的策略类,并根据具体场景选择合适的策略,增加了客户端的复杂度。
- 如果策略类较多,会导致类的数量增多,增加系统的复杂度。
应用场景
- 当一个系统中存在多个类只有它们的行为或算法不同时。
- 当一个类定义了多种行为,而这些行为在这个类的操作中以多个条件语句的形式出现,可以将相关的条件分支移入它们各自的策略类中,以替换这些条件语句。
- 当系统需要动态地在几种算法中选择一种时,如根据不同的配置、用户选择或者环境条件等。
总结
策略模式是一种行为型设计模式,通过封装一系列算法并使它们可以相互替换,实现了算法的变化独立于使用它的客户。策略模式在实际开发中应用较为广泛,如排序算法、缓存策略、支付方式等。在合适的场景下使用策略模式,可以提高代码的复用性、可维护性和灵活性。
原文链接: https://juejin.cn/post/7361323016041447461
文章收集整理于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除,如若转载,请注明出处:http://www.cxyroad.com/17886.html