策略模式的实现与应用:掌握灵活算法切换的技巧

文章目录


常用的设计模式有以下几种:

一.创建型模式(Creational Patterns):

工厂模式(Factory Pattern)

抽象工厂模式(Abstract Factory Pattern)

单例模式(Singleton Pattern)

原型模式(Prototype Pattern)

建造者模式(Builder Pattern)

二.结构型模式(Structural Patterns):

适配器模式(Adapter Pattern)

桥接模式(Bridge Pattern)

装饰器模式(Decorator Pattern)

组合模式(Composite Pattern)

外观模式(Facade Pattern)

享元模式(Flyweight Pattern)

代理模式(Proxy Pattern)

三.行为型模式(Behavioral Patterns):

策略模式(Strategy Pattern)

观察者模式(Observer Pattern)

迭代器模式(Iterator Pattern)

命令模式(Command Pattern)

模板方法模式(Template Method Pattern)

职责链模式(Chain of Responsibility Pattern)

状态模式(State Pattern)

访问者模式(Visitor Pattern)

中介者模式(Mediator Pattern)

备忘录模式(Memento Pattern)

解释器模式(Interpreter Pattern)

四.并发模式(Concurrent Patterns):

单例模式(Singleton Pattern,在多线程环境下的应用)

生成器模式(Builder Pattern,在多线程环境下的应用)

保护性暂停模式(Guarded Suspension Pattern)

观察者模式(Observer Pattern,在多线程环境下的应用)

这些设计模式涵盖了对象的创建、对象间的组织和交互、以及对象的行为等方面,可以帮助开发者更好地组织和设计代码,提高代码的可扩展性、可维护性以及重用性。需要根据实际情况选择适合的设计模式来解决问题。


策略模式概念

今天来讲一讲策略模式:
策略模式(Strategy Pattern)是一种行为设计模式,它允许你定义一系列算法,并将每个算法封装到独立的类中,使它们可以互相替换。策略模式使得算法的变化独立于使用它们的客户端。
在策略模式中,有一个上下文(Context)对象,它持有一个策略接口的引用,并通过调用策略接口的方法来执行具体的算法。算法类实现了策略接口,每个算法类都封装了一种具体的算法,客户端可以根据需要选择不同的策略对象,从而实现不同的行为。🤩🤩🤩
策略模式的优点包括:

1. 算法可以灵活地替换或新增,不影响使用算法的客户端。
2. 可以消除大量的条件语句,提高代码的可维护性和可读性。
3. 可以将算法的实现细节封装起来,提高代码的模块性和复用性。

策略模式在许多场景下都有应用,比如排序算法、计算费用、验证用户等。通过使用策略模式,可以优雅地处理复杂的逻辑,并提供一种可扩展、易于维护的解决方案。🤗🤗🤗

我并不喜欢看含义,对于这种概念性的东西,动手实践才是硬道理!
以下举出 策略模式 的几个 荔枝!!!😍😍😍
相信看完会更加理解策略模式的强大性!

一、策略模式例子一

假设我们正在开发一个商场收银系统,其中有不同的折扣策略供用户选择,包括无折扣、固定折扣和打折折扣。我们希望通过策略模式来实现这些不同的折扣策略。
首先,我们定义一个抽象的策略接口 DiscountStrategy,它声明了一个计算折扣金额的方法 calculateDiscount:

java 复制代码
public interface DiscountStrategy {
    double calculateDiscount(double amount);
}

然后,我们分别实现三种具体的策略类:NoDiscountStrategy(无折扣)、FixedDiscountStrategy(固定折扣)和PercentageDiscountStrategy(打折折扣)。它们都实现了 DiscountStrategy 接口:

java 复制代码
public class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public double calculateDiscount(double amount) {
        return 0; // 无折扣,返回0
    }
}

public class FixedDiscountStrategy implements DiscountStrategy {
    private double discount;

    public FixedDiscountStrategy(double discount) {
        this.discount = discount;
    }

    @Override
    public double calculateDiscount(double amount) {
        return discount; // 固定折扣,直接返回固定的折扣金额
    }
}

public class PercentageDiscountStrategy implements DiscountStrategy {
    private double percentage;

    public PercentageDiscountStrategy(double percentage) {
        this.percentage = percentage;
    }

    @Override
    public double calculateDiscount(double amount) {
        return amount * percentage; // 打折折扣,根据折扣比例计算折扣金额
    }
}

最后,我们定义一个上下文类 Cashier,它持有一个 DiscountStrategy 的引用,并在结算时调用该策略的方法:

java 复制代码
public class Cashier {
    private DiscountStrategy discountStrategy;

    public void setDiscountStrategy(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public double calculateTotalWithDiscount(double amount) {
        double discount = discountStrategy.calculateDiscount(amount);
        return amount - discount;
    }
}

现在,我们可以使用策略模式来实现商场收银系统的折扣功能了。示例如下:

java 复制代码
public class Main {
    public static void main(String[] args) {
        Cashier cashier = new Cashier();

        // 设置无折扣策略
        DiscountStrategy noDiscountStrategy = new NoDiscountStrategy();
        cashier.setDiscountStrategy(noDiscountStrategy);
        double total = cashier.calculateTotalWithDiscount(100);
        System.out.println("Total with no discount: " + total);

        // 设置固定折扣策略
        DiscountStrategy fixedDiscountStrategy = new FixedDiscountStrategy(20);
        cashier.setDiscountStrategy(fixedDiscountStrategy);
        total = cashier.calculateTotalWithDiscount(100);
        System.out.println("Total with fixed discount: " + total);

        // 设置打折折扣策略
        DiscountStrategy percentageDiscountStrategy = new PercentageDiscountStrategy(0.1);
        cashier.setDiscountStrategy(percentageDiscountStrategy);
        total = cashier.calculateTotalWithDiscount(100);
        System.out.println("Total with percentage discount: " + total);
    }
}

输出结果:

java 复制代码
Total with no discount: 100.0
Total with fixed discount: 80.0
Total with percentage discount: 90.0

通过策略模式,我们可以灵活地选择不同的折扣策略,并在运行时动态地切换和应用这些策略,而不需要修改 Cashier 类的代码。这样,我们可以方便地添加新的折扣策略或修改现有策略的实现,而不会对其他部分产生影响。这样的设计符合开闭原则,增加了代码的可维护性和扩展性。

二、策略模式例子二

例子2:排序算法
假设我们正在设计一个排序工具,它可以根据用户选择的不同排序算法对数据进行排序。我们可以使用策略模式来实现不同的排序策略。
首先,我们定义一个排序策略接口 SortingStrategy,它声明了一个排序方法 sort:

java 复制代码
public interface SortingStrategy {
    void sort(int[] array);
}

然后,我们分别实现两种具体的策略类:BubbleSortStrategy(冒泡排序)和 QuickSortStrategy(快速排序)。它们都实现了 SortingStrategy 接口:

java 复制代码
public class BubbleSortStrategy implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // 冒泡排序算法的具体实现
        // ...
    }
}

public class QuickSortStrategy implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // 快速排序算法的具体实现
        // ...
    }
}

最后,我们定义一个上下文类 Sorter,它持有一个 SortingStrategy 的引用,并在排序时调用该策略的方法:

java 复制代码
public class Sorter {
    private SortingStrategy sortingStrategy;

    public void setSortingStrategy(SortingStrategy sortingStrategy) {
        this.sortingStrategy = sortingStrategy;
    }

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

现在,我们可以使用策略模式来实现排序工具了。示例如下:

java 复制代码
public class Main {
    public static void main(String[] args) {
        Sorter sorter = new Sorter();

        // 使用冒泡排序策略
        SortingStrategy bubbleSortStrategy = new BubbleSortStrategy();
        sorter.setSortingStrategy(bubbleSortStrategy);
        int[] array = {5, 3, 8, 2, 1};
        sorter.sortArray(array);
        System.out.println("Sorted array using bubble sort:");
        for (int num : array) {
            System.out.print(num + " ");
        }
        System.out.println();

        // 使用快速排序策略
        SortingStrategy quickSortStrategy = new QuickSortStrategy();
        sorter.setSortingStrategy(quickSortStrategy);
        int[] array2 = {9, 4, 6, 2, 7};
        sorter.sortArray(array2);
        System.out.println("Sorted array using quick sort:");
        for (int num : array2) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
}

输出结果:

java 复制代码
Sorted array using bubble sort:
1 2 3 5 8 
Sorted array using quick sort:
2 4 6 7 9

通过策略模式,我们可以灵活地选择不同的排序策略,而不需要修改 Sorter 类的代码。这样,我们可以方便地添加新的排序策略或修改现有策略的实现,而不会对其他部分产生影响。

三、策略模式例子三

假设我们正在开发一个电商平台,针对不同的用户类型(普通用户、VIP用户、管理员),我们需要为其提供不同的登录方式。
首先,我们定义一个登录策略接口 LoginStrategy,它声明了一个登录方法 login:

java 复制代码
public interface LoginStrategy {
    void login();
}

然后,我们分别实现三种具体的策略类:DefaultLoginStrategy(普通用户登录方式)、VIPLoginStrategy(VIP用户登录方式)和 AdminLoginStrategy(管理员登录方式)。它们都实现了 LoginStrategy 接口:

java 复制代码
public class DefaultLoginStrategy implements LoginStrategy {
    @Override
    public void login() {
        System.out.println("使用用户名和密码登录");
        // 具体的登录逻辑
    }
}

public class VIPLoginStrategy implements LoginStrategy {
    @Override
    public void login() {
        System.out.println("使用手机号和密码登录");
        // 具体的登录逻辑
    }
}

public class AdminLoginStrategy implements LoginStrategy {
    @Override
    public void login() {
        System.out.println("使用管理员账号和密码登录");
        // 具体的登录逻辑
    }
}

最后,我们定义一个上下文类 LoginContext,它持有一个 LoginStrategy 的引用,并在登录时调用该策略的方法:

java 复制代码
public class LoginContext {
    private LoginStrategy loginStrategy;

    public void setLoginStrategy(LoginStrategy loginStrategy) {
        this.loginStrategy = loginStrategy;
    }

    public void performLogin() {
        loginStrategy.login();
    }
}

现在,我们可以使用策略模式来为不同的用户类型提供不同的登录方式了。示例如下:

java 复制代码
public class Main {
    public static void main(String[] args) {
        LoginContext loginContext = new LoginContext();

        // 普通用户登录
        LoginStrategy defaultLoginStrategy = new DefaultLoginStrategy();
        loginContext.setLoginStrategy(defaultLoginStrategy);
        loginContext.performLogin();

        // VIP用户登录
        LoginStrategy vipLoginStrategy = new VIPLoginStrategy();
        loginContext.setLoginStrategy(vipLoginStrategy);
        loginContext.performLogin();

总结

UU们,懂了嘛!!!😄😄😄

以下是实际开发中常用的几个例子,展示了策略模式的应用:

支付方式:

在电商平台上,用户可以选择不同的支付方式进行支付,比如支付宝、微信支付、银行卡支付等。这些支付方式都具备支付的功能,但其实现方式和支付逻辑可能有所不同。策略模式可以用于将不同的支付方式封装成不同的策略类,然后在运行时根据用户选择的支付方式来选择相应的策略进行支付。

缓存策略:

在系统开发中,我们经常会使用缓存来提高系统性能。不同的数据操作可能需要不同的缓存策略,比如基于时间的过期策略、基于LRU(Least

Recently Used)的淘汰策略、基于LFU(Least Frequently

Used)的淘汰策略等。策略模式可以用于封装不同的缓存策略为不同的策略类,然后在运行时选择相应的缓存策略进行数据操作。

图像处理:

在图像处理应用中,我们可能需要应用不同的滤镜或特效来处理图像,比如黑白滤镜、模糊滤镜、锐化滤镜等。这些滤镜都具备处理图像的功能,但实现方式和处理逻辑可能有所不同。策略模式可以用于将不同的滤镜或特效封装成不同的策略类,然后在运行时根据用户选择的滤镜或特效来选择相应的策略进行图像处理。

日志记录级别:

在日志记录应用中,不同的日志级别对应不同的日志输出方式,比如普通日志输出到控制台,警告日志输出到文件,错误日志发送邮件等等。策略模式可以用于封装不同的日志记录级别为不同的策略类,然后在运行时根据日志级别选择相应的策略进行日志记录。

这些都是在实际开发中常用的例子,策略模式可以帮助我们根据不同的条件和需求来选择相应的策略进行处理,提供了灵活性和扩展性。它可以将不同的策略封装起来,使客户端代码与具体策略的实现解耦,从而提高代码的可维护性和可测试性。

(注意:是不同的处理逻辑,如果你只是根据不同类型查数据库一张表的数据,那就没啥必要了)

不懂或者有什么错误的地方,欢迎评论区留言,俺可以再举更多的 荔枝~~~

@作者:加辣椒了吗?

简介:憨批大学生一枚,喜欢在博客上记录自己的学习心得,也希望能够帮助到你们!

相关推荐
秋の花几秒前
【JAVA基础】Java集合基础
java·开发语言·windows
香菜大丸几秒前
链表的归并排序
数据结构·算法·链表
jrrz08281 分钟前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
小松学前端3 分钟前
第六章 7.0 LinkList
java·开发语言·网络
Wx-bishekaifayuan10 分钟前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava
oliveira-time12 分钟前
golang学习2
算法
customer0814 分钟前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
全栈开发圈16 分钟前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫
WaaTong19 分钟前
《重学Java设计模式》之 单例模式
java·单例模式·设计模式