【设计模式 行为型】策略模式

它允许在运行时根据需要选择算法的行为。该模式通过将算法封装成独立的类,使得它们可以相互替换,而不影响使用算法的客户端代码。

策略模式主要包含以下角色:

  1. 环境(Context):环境对象持有一个策略对象的引用,它提供了一个接口用于执行具体的算法。
  2. 抽象策略(Strategy):定义了策略类的统一接口,用于约束具体策略类的行为。
  3. 具体策略(Concrete Strategy):实现了抽象策略定义的接口,具体实现算法逻辑。

下面以一个简单的支付系统为例来说明策略模式的应用:

java 复制代码
// 抽象策略类
public interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略类
public class AliPayStrategy implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("使用支付宝支付:" + amount + "元");
        // 具体的支付逻辑
    }
}

public class WeChatPayStrategy implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("使用微信支付:" + amount + "元");
        // 具体的支付逻辑
    }
}

// 环境类
@Data
@NoArgsConstructor
public class PaymentContext {
    private PaymentStrategy strategy;

    public void pay(double amount) {
        strategy.pay(amount);
    }
}

在上述示例中,我们定义了一个抽象策略类PaymentStrategy,并有两个具体的策略类AliPayStrategyWeChatPayStrategy分别实现了支付宝支付和微信支付的具体逻辑。

环境类PaymentContext持有一个策略对象的引用,并提供了设置策略和支付方法。客户端通过设置不同的策略对象来实现不同的支付方式。这样,客户端代码与具体的支付算法解耦,可以动态地在运行时切换支付策略。

下面是使用策略模式实现的客户端代码:

java 复制代码
javaCopy Codepublic class Client {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext();

        // 使用支付宝支付
        PaymentStrategy aliPayStrategy = new AliPayStrategy();
        context.setPaymentStrategy(aliPayStrategy);
        context.pay(100.0);

        // 使用微信支付
        PaymentStrategy weChatPayStrategy = new WeChatPayStrategy();
        context.setPaymentStrategy(weChatPayStrategy);
        context.pay(200.0);
    }
}

运行上述客户端代码,输出如下:

Copy Code 使用支付宝支付:100.0 元

使用微信支付:200.0 元

通过策略模式,我们可以轻松地在运行时切换不同的支付方式,而不需要改动客户端代码。策略模式将算法的选择和使用进行了解耦,提高了代码的灵活性和可维护性。同时,策略模式也符合开闭原则,当需要新增一种支付方式时,只需要添加新的具体策略类即可,无需修改原有代码逻辑。

java 复制代码
public class Client {
    public static void main(String[] args) {
        double price = 100.0;
        String type = "normal";
        double discount = 1.0;

        // 根据商品类型设置折扣率
        if (type.equals("vip")) {
            discount = 0.9;
        } else if (type.equals("member")) {
            discount = 0.95;
        } else if (type.equals("promotion")) {
            discount = 0.8;
        }

        double actualPrice = price * discount;
        System.out.println("商品的实际价格为:" + actualPrice);
    }
}

上述代码中,我们根据商品类型手动设置相应的折扣率,然后计算实际价格。这样的代码虽然简单,但存在以下问题:

  1. 客户端代码与具体的折扣算法高度耦合,如果需要更改算法,例如新增一种商品类型,就需要修改客户端代码,这会导致代码的可维护性变差。
  2. 没有遵循开闭原则,当需要新增一种商品类型时,就需要修改原有代码逻辑,这样会影响到其他代码的稳定性。

因此,采用策略模式能更好地解决这些问题,实现代码的松耦合和可维护性。

java 复制代码
public class CeLue {

    public static void main(String[] args) {
        double price = 100.0;
        String type = "vip";
        PayStrategy conType = getPayStrategy(type);
        PayContext payContext = new PayContext(conType);
        payContext.pay(price);
    }

    private static PayStrategy getPayStrategy(String type) {
        switch (type) {
            case "vip":
                return new VipType();
            default:
                return new NormalType();
        }
    }
}

interface PayStrategy {
    void pay(double amount);
}

class NormalType implements PayStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("普通支付" + amount + "元");
    }
}

class VipType implements PayStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("vip支付" + amount * 0.9 + "元");
    }
}

class PayContext {
    private PayStrategy payStrategy;

    public PayContext(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }

    public void pay(double amount) {
        payStrategy.pay(amount);
    }

}
相关推荐
画中有画19 分钟前
软件架构中质量属性(性能、安全、可扩展性)的权衡设计
java·运维·安全
Shaoxi Zhang36 分钟前
JAVA学习笔记035——对象和JSON格式
java·笔记·学习
赵丙双37 分钟前
CountDownLatch 源码分析
java·aqs·countdownlatch
余额瞒着我当琳1 小时前
C++--深拷贝三件套 + swap + 写时拷贝 + vector 扩容 + reserve
java·开发语言·c++
thefool1122661 小时前
翻转二叉树
java
东方小月1 小时前
从零开发一个 Coding Agent(十二):实现版本化 JSONL 与真实 CLI 入口
前端·设计模式·前端框架
喜欢打篮球的普通人2 小时前
LLVM Backend Lowering 从入门到实战:把 IR 变成机器码的完整链路
android·java·数据库
FL16238631292 小时前
室内易燃物识别易燃评估室内易燃程度识别分割数据集labelme格式1015张85类别
java·服务器·前端
jufeng13073 小时前
【系列:TDengine 工业物联网实战:从零搭起可运行系统 · 第 8 篇】
java·spring boot·时序数据库·tdengine
程序员贺加贝3 小时前
轻制造SaaS的生产闭环建模-BOM工单领料报工质检与入库
java·设计模式·架构