电影院售票 - 策略模式(Strategy Pattern)

策略模式(Strategy Pattern)

策略模式(Strategy Pattern)

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法独立于使用它的客户端而变化,从而提高了代码的灵活性和可维护性。

太抽象了

还是举个现实生活中的例子,假如我们现在要设计一个电影院售票系统,我们要给不同的客户提供不同的折扣,比如说:老年人半价,学生票半价,小朋友多少岁之前免票之类的。怎么办?你可能像,我们直接if else不就好了。也许开始的时候是可以实现我们的要求的,但是如果我们现在要增加活动,学生积分抵现,或者看5次免一次票价活动,你想想我们如果要在之前的ifelse里面做改动的话,会导致修改的量很大,而且还非常容易出错。那有没有更好的实现方式呢? 策略模式(Strategy Pattern)

策略模式概述

策略模式结构图

策略模式主要包含的角色

  1. 策略接口(Strategy):定义了所有支持算法公共操作的接口或抽象类。具体策略类必须实现这个接口中的方法。
java 复制代码
public interface Strategy {
    void execute();
}
  1. 具体策略(ConcreteStrategy):实现了 Strategy 接口的具体类。每个具体策略都提供了一种算法的实现方式。
java 复制代码
public class ConcreteStrategyA implements Strategy {
    @Override
    public void execute() {
        System.out.println("strategy A");
    }
}

public class ConcreteStrategyB implements Strategy {
    @Override
    public void execute() {
        System.out.println("strategy B");
    }
}
  1. 上下文(Context):上下文类拥有一个对策略对象的引用,并提供了设置和获取策略的方法。上下文委托给策略对象来执行具体的算法逻辑。
java 复制代码
public class Context {
    private Strategy strategy;

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

    // 执行策略
    public void executeStrategy() {
        if (strategy != null) {
            strategy.execute();
        } else {
            System.out.println("Strategy not set");
        }
    }
}

talk is cheap, show you my code

java 复制代码
// 策略接口
interface PricingStrategy {
    double calculatePrice(double basePrice);
}
 
// 成人票价策略
class AdultPricingStrategy implements PricingStrategy {
    @Override
    public double calculatePrice(double basePrice) {
        // 假设成人票价没有折扣
        return basePrice;
    }
}
 
// 儿童票价策略
class ChildPricingStrategy implements PricingStrategy {
    @Override
    public double calculatePrice(double basePrice) {
        // 假设儿童票价是半价
        return basePrice / 2;
    }
}
 
// 学生票价策略
class StudentPricingStrategy implements PricingStrategy {
    @Override
    public double calculatePrice(double basePrice) {
        // 假设学生票价有8折优惠
        return basePrice * 0.8;
    }
}
 
// 电影票类
class MovieTicket {
    private String movieName;
    private double basePrice;
    private PricingStrategy pricingStrategy;
 
    public MovieTicket(String movieName, double basePrice, PricingStrategy pricingStrategy) {
        this.movieName = movieName;
        this.basePrice = basePrice;
        this.pricingStrategy = pricingStrategy;
    }
 
    public double getPrice() {
        return pricingStrategy.calculatePrice(basePrice);
    }
 
    @Override
    public String toString() {
        return "MovieTicket{" +
                "movieName='" + movieName + '\'' +
                ", price=" + getPrice() +
                '}';
    }
}
 
// 客户端类
public class CinemaTicketingSystem {
    public static void main(String[] args) {
        double basePrice = 100.0; // 假设基础票价为100元
 
        // 创建不同的票价策略
        PricingStrategy adultStrategy = new AdultPricingStrategy();
        PricingStrategy childStrategy = new ChildPricingStrategy();
        PricingStrategy studentStrategy = new StudentPricingStrategy();
 
        // 创建电影票对象
        MovieTicket adultTicket = new MovieTicket("Inception", basePrice, adultStrategy);
        MovieTicket childTicket = new MovieTicket("Inception", basePrice, childStrategy);
        MovieTicket studentTicket = new MovieTicket("Inception", basePrice, studentStrategy);
 
        // 打印票价
        System.out.println(adultTicket); // MovieTicket{movieName='Inception', price=100.0}
        System.out.println(childTicket);  // MovieTicket{movieName='Inception', price=50.0}
        System.out.println(studentTicket); // MovieTicket{movieName='Inception', price=80.0}
    }
}

在这个例子中,PricingStrategy接口定义了计算票价的方法。AdultPricingStrategy、ChildPricingStrategy和StudentPricingStrategy类分别实现了这个接口,并提供了不同的计算逻辑。MovieTicket类有一个PricingStrategy类型的成员变量,用于存储当前电影票所使用的票价策略。在getPrice方法中,它调用策略对象的calculatePrice方法来计算票价。

总结

策略模式的优点

  • 算法与客户端分离:通过将算法封装在独立的策略类中,使得算法的实现细节对客户端透明。
  • 易于扩展:新增加一种算法只需添加一个新的具体策略类,而不必修改现有的代码。
  • 符合开闭原则:当需要添加新的策略时,只需创建新的策略类,而不需要改变已有的代码。
  • 避免条件语句:使用策略模式可以减少代码中的条件判断语句,提高代码的清晰度和可读性。

策略模式缺点

  • 增加类的数量
  • 客户端需要知道所有的策略
  • 接口定义困难
  • 策略的组合与复用有限
  • 简单场景不建议使用策略模式

策略模式的应用场景

  • 不同支付方式:如现金、信用卡、支付宝等支付方式的选择可以通过策略模式来实现。
  • 排序算法:根据数据量大小选择不同的排序算法(快速排序、插入排序等),也可以用策略模式来管理。
  • 日志记录:不同的日志级别(DEBUG、INFO、ERROR等)可以有不同的处理方式,这些都可以作为策略来实现。
  • 游戏AI:在游戏中,NPC的行为可以根据玩家的动作或环境状态来动态调整,这也可以通过策略模式来实现。

策略模式是一个非常有用的设计模式,特别是在需要根据不同情况选择不同算法或行为的时候。它可以帮助我们更好地组织代码,提高系统的灵活性和可维护性。

相关推荐
heart000_19 分钟前
基于SpringBoot的智能问诊系统设计与隐私保护策略
java·spring boot·后端
半聋半瞎15 分钟前
【进程和线程】(面试高频考点)
java·jvm·面试
功德+n27 分钟前
在 Maven 中使用 <scope> 元素:全面指南
java·maven
失业写写八股文1 小时前
Java类加载阶段深度解析:三步走全流程详解
java
yyueshen1 小时前
单例模式,有必要用volatile么?
java·单例模式·设计模式
一条闲鱼_mytube1 小时前
[Kubernetes] 7控制平面组件
java·平面·kubernetes
Y雨何时停T1 小时前
Spring IoC 详解
java·spring·rpc
千益2 小时前
玩转python:系统设计模式在Python项目中的应用
python·设计模式
&白帝&2 小时前
Java @PathVariable获取路径参数
java·开发语言·python
Yuanymoon2 小时前
【由技及道】镜像星门开启:Harbor镜像推送的量子跃迁艺术【人工智障AI2077的开发日志010】
java·docker·jenkins·harbor·devops