欢迎访问宙启技术站
智能推送

PHP设计模式之 策略模式Strategy详解【对象行为型】

发布时间:2023-05-18 10:29:26

策略模式(Strategy Pattern)是一种对象行为型设计模式,它定义了一系列算法,将每个算法封装起来,使它们可以互换使用,而且算法的变化不会影响到使用算法的客户端。

使用策略模式的一个典型场景是:一个对象可能有多种处理方式,而且在不同的情况下需要使用不同的处理方式。举一个简单的例子:对于一个可以排序的对象,我们可以使用冒泡排序、快速排序等多种算法来实现排序功能,而策略模式就可以将这些排序算法封装到不同的策略类中,使得客户端代码可以根据不同的需求选择不同的排序算法,而不需要知道具体的实现细节。

策略模式的 UML 类图如下所示:

![Strategy Pattern UML Class Diagram](https://img-blog.csdn.net/20170401215659516?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYmFpNzIw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/70)

在策略模式中,具体策略类(ConcreteStrategy)实现了抽象策略类(Strategy)定义的接口。在客户端代码中,调用 Context 类的方法来实现具体业务逻辑,但是 Context 类并不是直接处理具体业务逻辑的,而是将请求委托给了某个具体策略类,委托它来处理具体的业务逻辑。

下面我们通过一个实例来说明策略模式的具体应用。

例:电影票打折活动与策略模式

我们现在有一个电影票销售系统,该系统按照电影的不同时间段和不同人群提供不同的打折活动,如平日票打九折、周末票打八折、学生票打六折等。对于客户端而言,它们只需要选择所需的电影票种类和数量,然后系统自动根据所选票的种类和数量进行打折,计算出需要付的金额。

根据上面的需求,我们可以定义一个抽象策略接口 DiscountStrategy,该接口中包含了一个计算打折价的方法 calculateDiscount(double price):

/**
 * 折扣类:抽象策略类
 */
public interface DiscountStrategy {
    /**
     * 计算折扣价格
     * @param price 原价
     * @return 折扣价
     */
    double calculateDiscount(double price);
}

接下来,我们可以定义多个具体的折扣算法类,如平日票打九折、周末票打八折等,这些折扣算法类都实现了 DiscountStrategy 接口的 calculateDiscount(double price) 方法:

/**
 * 平日票折扣类:具体策略类
 */
public class WeekdayDiscountStrategy implements DiscountStrategy {
    public double calculateDiscount(double price) {
        System.out.println("使用平日票折扣策略计算折扣...");
        return price * 0.9;
    }
}

/**
 * 周末票折扣类:具体策略类
 */
public class WeekendDiscountStrategy implements DiscountStrategy {
    public double calculateDiscount(double price) {
        System.out.println("使用周末票折扣策略计算折扣...");
        return price * 0.8;
    }
}

/**
 * 学生票折扣类:具体策略类
 */
public class StudentDiscountStrategy implements DiscountStrategy {
    public double calculateDiscount(double price) {
        System.out.println("使用学生票折扣策略计算折扣...");
        return price * 0.6;
    }
}

接下来,我们将折扣类作为上下文 Context 的属性,根据所选票的种类和数量来动态选择相应的折扣类:

/**
 * 电影票
 */
public class MovieTicket {

    private double price; // 票价

    private DiscountStrategy discountStrategy; // 维持一个对折扣类对象的引用

    public double getPrice() {
        return discountStrategy.calculateDiscount(this.price); // 调用策略对象的算法来计算折扣价格
    }

    public void setPrice(double price) {
        this.price = price;
    }

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

最后,我们可以编写一个简单的客户端来测试我们的代码:

public class Client {

    public static void main(String[] args) {
        MovieTicket ticket = new MovieTicket();
        ticket.setPrice(60);
        DiscountStrategy strategy = new StudentDiscountStrategy();
        ticket.setDiscountStrategy(strategy);
        System.out.println("原始票价:" + ticket.price);
        System.out.println("折后价:" + ticket.getPrice());
    }
}

上述代码中,客户端通过 setDiscountStrategy(DiscountStrategy strategy) 方法来动态设置电影票使用的折扣策略,而 getPrice() 方法则根据当前选定的折扣策略来计算折后价。

运行上述代码,我们可以得到以下输出结果:

原始票价:60.0
使用学生票折扣策略计算折扣...
折后价:36.0

可以看出,我们的代码成功地根据客户端所选的票种和数量动态地选择了适当的打折策略,并且计算出了正确的折扣价。

总结

策略模式的优点主要有两个:

1. 策略类之间可以自由切换,增加新的策略类也比较容易。

2. 避免了使用多重条件判断语句,使代码更清晰、更简洁。

策略模式通常适用于以下场景:

1. 多个类只有在算法/行为上稍有不同的场景。

2. 算法需要自由切换的场景。

3. 需要屏蔽算法/行为的场景。

以上就是策略模式的详细介绍及实例应用,希望能对大家有所帮助。