妙解设计模式之策略模式

目录

策略模式的概念

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,把它们一个个封装起来,并且使它们可以相互替换。这种模式使得算法可以独立于使用它的客户端而变化。

策略模式的关键点

  1. 策略接口(Strategy):定义所有策略(算法)共有的方法。
  2. 具体策略类(ConcreteStrategy):实现策略接口的具体算法。
  3. 上下文类(Context):持有一个策略对象,并在需要时调用这个策略的方法。

策略模式的优点

  1. 易于扩展:增加新算法时,只需添加新的具体策略类,不需要修改现有的代码。
  2. 避免使用多重条件语句 :通过使用策略模式,可以避免大量的 if-elseswitch 语句,使代码更加简洁和清晰。
  3. 提高代码的灵活性和可维护性:可以动态地改变算法,而不需要修改客户端代码。

策略模式的缺点

  1. 增加类的数量:每个具体策略都是一个单独的类,会导致类的数量增多,增加代码的复杂性。
  2. 所有策略类都需要暴露:策略类需要对外公开,以便可以被选择和使用。

生活中的例子

策略模式是一种设计模式,它允许你定义一系列算法(或者叫方法),然后在运行时选择其中一个来使用。就像你有一个装满不同类型武器的工具箱,每次打怪兽的时候,你可以选择最合适的武器来使用。

编程中的例子

策略接口

java 复制代码
// 定义策略接口
public interface AttackStrategy {
    void attack();
}

这个接口定义了一个 attack 方法,所有的具体策略类都需要实现这个方法。

具体策略类

java 复制代码
// 使用剑攻击
public class SwordAttack implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("使用剑攻击怪兽!");
    }
}

// 使用弓箭攻击
public class BowAndArrowAttack implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("使用弓箭攻击怪兽!");
    }
}

// 使用魔法攻击
public class MagicAttack implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("使用魔法攻击怪兽!");
    }
}

这些类实现了 AttackStrategy 接口,并提供了具体的攻击方法。

上下文类

java 复制代码
// 上下文类
public class MonsterHunter {
    private AttackStrategy strategy;

    // 设置策略
    public void setStrategy(AttackStrategy strategy) {
        this.strategy = strategy;
    }

    // 执行攻击
    public void attackMonster() {
        strategy.attack();
    }
}

上下文类 MonsterHunter 持有一个 AttackStrategy 对象,并在 attackMonster 方法中调用策略对象的 attack 方法。

使用策略模式

java 复制代码
public class Main {
    public static void main(String[] args) {
        MonsterHunter hunter = new MonsterHunter();
        
        // 使用剑攻击
        hunter.setStrategy(new SwordAttack());
        hunter.attackMonster();
        
        // 使用弓箭攻击
        hunter.setStrategy(new BowAndArrowAttack());
        hunter.attackMonster();
        
        // 使用魔法攻击
        hunter.setStrategy(new MagicAttack());
        hunter.attackMonster();
    }
}

在这个例子中,我们创建了一个 MonsterHunter 对象,并通过 setStrategy 方法动态设置不同的攻击策略。每次设置策略后,我们调用 attackMonster 方法来执行相应的攻击。

软件工程中的实际应用

数据排序

在应用程序中,你可能需要对数据进行排序,但不同情况下的排序规则可能不同。例如,有时候需要按名字排序,有时候需要按年龄排序。这时,可以使用策略模式定义不同的排序算法,并根据需要选择合适的算法。

java 复制代码
// 定义排序策略接口
public interface SortStrategy {
    void sort(int[] numbers);
}

// 具体策略类:冒泡排序
public class BubbleSort implements SortStrategy {
    @Override
    public void sort(int[] numbers) {
        // 实现冒泡排序算法
    }
}

// 具体策略类:快速排序
public class QuickSort implements SortStrategy {
    @Override
    public void sort(int[] numbers) {
        // 实现快速排序算法
    }
}

// 上下文类
public class Sorter {
    private SortStrategy strategy;

    public void setStrategy(SortStrategy strategy) {
        this.strategy = strategy;
    }

    public void sort(int[] numbers) {
        strategy.sort(numbers);
    }
}

// 使用策略模式进行排序
public class Main {
    public static void main(String[] args) {
        int[] numbers = {5, 2, 9, 1, 5, 6};
        Sorter sorter = new Sorter();

        sorter.setStrategy(new BubbleSort());
        sorter.sort(numbers);

        sorter.setStrategy(new QuickSort());
        sorter.sort(numbers);
    }
}

文件压缩

在文件压缩工具中,可能支持多种压缩算法,比如 ZIP、RAR、TAR 等。可以使用策略模式来选择不同的压缩算法

java 复制代码
// 定义压缩策略接口
public interface CompressionStrategy {
    void compress(String filePath);
}

// 具体策略类:ZIP压缩
public class ZipCompression implements CompressionStrategy {
    @Override
    public void compress(String filePath) {
        // 实现ZIP压缩算法
    }
}

// 具体策略类:RAR压缩
public class RarCompression implements CompressionStrategy {
    @Override
    public void compress(String filePath) {
        // 实现RAR压缩算法
    }
}

// 上下文类
public class Compressor {
    private CompressionStrategy strategy;

    public void setStrategy(CompressionStrategy strategy) {
        this.strategy = strategy;
    }

    public void compress(String filePath) {
        strategy.compress(filePath);
    }
}

// 使用策略模式进行文件压缩
public class Main {
    public static void main(String[] args) {
        Compressor compressor = new Compressor();

        compressor.setStrategy(new ZipCompression());
        compressor.compress("example.txt");

        compressor.setStrategy(new RarCompression());
        compressor.compress("example.txt");
    }
}

支付方式

在电商网站中,用户可能使用不同的支付方式,例如信用卡支付、PayPal 支付、银行转账等。可以使用策略模式来实现不同的支付方式。

java 复制代码
// 定义支付策略接口
public interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略类:信用卡支付
public class CreditCardPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        // 实现信用卡支付
    }
}

// 具体策略类:PayPal支付
public class PayPalPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        // 实现PayPal支付
    }
}

// 上下文类
public class PaymentProcessor {
    private PaymentStrategy strategy;

    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

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

// 使用策略模式进行支付
public class Main {
    public static void main(String[] args) {
        PaymentProcessor processor = new PaymentProcessor();

        processor.setStrategy(new CreditCardPayment());
        processor.processPayment(100.0);

        processor.setStrategy(new PayPalPayment());
        processor.processPayment(100.0);
    }
}

图形绘制

在图形应用程序中,可能需要使用不同的绘制算法,比如绘制线条、绘制矩形、绘制圆形等。可以使用策略模式来封装不同的绘制算法。

java 复制代码
// 定义绘制策略接口
public interface DrawStrategy {
    void draw();
}

// 具体策略类:绘制线条
public class DrawLine implements DrawStrategy {
    @Override
    public void draw() {
        // 实现绘制线条的算法
    }
}

// 具体策略类:绘制矩形
public class DrawRectangle implements DrawStrategy {
    @Override
    public void draw() {
        // 实现绘制矩形的算法
    }
}

// 具体策略类:绘制圆形
public class DrawCircle implements DrawStrategy {
    @Override
    public void draw() {
        // 实现绘制圆形的算法
    }
}

// 上下文类
public class GraphicEditor {
    private DrawStrategy strategy;

    public void setStrategy(DrawStrategy strategy) {
        this.strategy = strategy;
    }

    public void draw() {
        strategy.draw();
    }
}

// 使用策略模式进行绘图
public class Main {
    public static void main(String[] args) {
        GraphicEditor editor = new GraphicEditor();

        editor.setStrategy(new DrawLine());
        editor.draw();

        editor.setStrategy(new DrawRectangle());
        editor.draw();

        editor.setStrategy(new DrawCircle());
        editor.draw();
    }
}
相关推荐
芒果披萨8 分钟前
El表达式和JSTL
java·el
duration~1 小时前
Maven随笔
java·maven
zmgst1 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD1 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp1 小时前
Java:数据结构-枚举
java·开发语言·数据结构
独行soc2 小时前
#渗透测试#SRC漏洞挖掘#深入挖掘XSS漏洞02之测试流程
web安全·面试·渗透测试·xss·漏洞挖掘·1024程序员节
暗黑起源喵2 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong2 小时前
Java反射
java·开发语言·反射
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
九圣残炎2 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode