设计模式-策略

什么是策略模式

策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时根据不同的情况选择不同的算法或行为。

该模式的核心思想是将不同的算法封装成独立的策略类,并使它们能够互相替换,而不影响客户端代码。通过这种方式,客户端可以根据需要在运行时选择合适的策略来完成特定的任务。

使用策略模式可以使代码更加灵活、可扩展和可维护。它将不同的算法封装成独立的策略类,使得新增或修改算法变得简单,同时还能避免代码中的大量条件语句。

总结起来,策略模式通过将算法封装成独立的策略类,实现了算法与客户端的解耦,使得算法可以灵活地切换和扩展,从而提供了一种优雅的方式来处理不同的行为需求。

策略模式组成

策略模式通常涉及三个主要角色:

  • 策略接口(Strategy Interface):定义了策略类需要实现的方法,它通常作为不同策略类的公共接口。
  • 策略类(Strategy Class):实现了策略接口的具体算法或行为。每个策略类都封装了一种特定的算法,并提供了相应的实现逻辑。
  • 上下文类(Context Class):包含了一个策略接口的引用,它提供了一个设置和切换策略的方法。上下文类将具体的任务委托给策略对象来执行,而不直接实现具体的算法。

策略模式的通用代码

// 策略接口
interface SortingStrategy {
    void sort(int[] array);
}

// 策略类1:冒泡排序
class BubbleSort implements SortingStrategy {
    public void sort(int[] array) {
        System.out.println("Sorting using Bubble Sort");
        // 冒泡排序的具体实现逻辑
    }
}

// 策略类2:快速排序
class QuickSort implements SortingStrategy {
    public void sort(int[] array) {
        System.out.println("Sorting using Quick Sort");
        // 快速排序的具体实现逻辑
    }
}

// 上下文类
class SortContext {
    private SortingStrategy strategy;

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

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

// 客户端代码
public class Main {
    public static void main(String[] args) {
        int[] array = {5, 2, 8, 1, 9};

        SortContext context = new SortContext();

        // 使用冒泡排序策略
        context.setStrategy(new BubbleSort());
        context.sortArray(array);

        // 使用快速排序策略
        context.setStrategy(new QuickSort());
        context.sortArray(array);
    }
}

当然,在我们的实际开发上,用策略模式来代替if-else会更加常用一点。在这种情况下,直接设置一个固定的策略显然并不满足我们的期望。我们需要其自动匹配合适的策略。

策略模式 替换if-else

假设我们要处理一个office文件,分为三种类型 docx、xlsx、pptx,分别表示Word文件、Excel文件、PPT文件,根据文件后缀分别解析。

if-else 写法

    public void handleFile(String filePath){
        if(filePath == null){
            return;
        }
        String fileExtension = getFileExtension(filePath);
        if(("docx").equals(fileExtension)){
            handlerDocx(filePath);
        }else if(("xlsx").equals(fileExtension)){
            handlerXlsx(filePath);
        }else if(("pptx").equals(fileExtension)){
            handlerPptx(filePath);
        }
    }
    private static String getFileExtension(String filePath){
        // 解析文件名获取文件扩展名,比如 文档.docx,返回 docx
        String fileExtension = filePath.substring(filePath.lastIndexOf(".")+1);
        return fileExtension;
    }

处理逻辑全部放在一个类中,会导致整个类特别庞大,假设我们要新增一种类型处理,比如对于2007版之前的office文件,后缀分别是 doc/xls/ppt,那我们得增加 else if 逻辑,违反了开闭原则,如何解决这种问题呢,答案就是通过策略模式。

策略模式改写

/**
     * 存放所有文件的解析策略
     */
    private Map<String, Function<String, Map<String ,Object> >> strategyMap = new HashMap<>(16);

{
        strategyMap.put("docx",(arg) -> handlerStrategy.docx_handler(arg));
		strategyMap.put("xlsx",(arg) -> handlerStrategy.xlsx_handler(arg));
		strategyMap.put("pptx",(arg) -> handlerStrategy.pptx_handler(arg));

    }
 public void handleFile(String filePath){
        if(filePath == null){
            return;
        }
        String fileExtension = getFileExtension(filePath);
        if (strategyMap.containsKey(fileExtension )) {
            resMap = strategyMap.get(fileExtension ).apply(filePath);
        }
 }


不过,这显然是一种偷懒的写法:将所有的策略都写在了一个类handlerStrategy里面。使用时需要甄别,并选择合适的方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值