当前位置: 首页 > article >正文

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

策略模式(Strategy Pattern)

  • 策略模式(Strategy Pattern)
    • 策略模式概述
    • 策略模式结构图
      • 策略模式主要包含的角色
    • talk is cheap, show you my code
    • 总结

策略模式(Strategy Pattern)

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

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

策略模式概述

策略模式结构图

在这里插入图片描述

策略模式主要包含的角色

  1. 策略接口(Strategy):定义了所有支持算法公共操作的接口或抽象类。具体策略类必须实现这个接口中的方法。
public interface Strategy {
    void execute();
}
  1. 具体策略(ConcreteStrategy):实现了 Strategy 接口的具体类。每个具体策略都提供了一种算法的实现方式。
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):上下文类拥有一个对策略对象的引用,并提供了设置和获取策略的方法。上下文委托给策略对象来执行具体的算法逻辑。
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

// 策略接口
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的行为可以根据玩家的动作或环境状态来动态调整,这也可以通过策略模式来实现。

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


http://www.kler.cn/a/465294.html

相关文章:

  • 中高级运维工程师运维面试题(十一)之 Docker
  • 三、GIT与Github推送(上传)和克隆(下载)
  • 01 数据分析介绍及工具准备
  • Ajax原理-XMLHttpRequest
  • 组网实训实现
  • C++编程库与框架实战——ZeroMQ消息队列
  • github提交不上去,网络超时问题解决
  • 【AIGC】ChatGPT 记忆功能揭秘:使用与管理的全方位指南
  • 计算帐户每月余额,补齐缺失日期:从 SQL 到 SPL
  • Luma AI 简单几步生成视频
  • SpringMVC(一)配置
  • 【OpenCV】使用Python和OpenCV实现火焰检测
  • Spring Boot 中 TypeExcludeFilter 的作用及使用示例
  • 数据挖掘——聚类
  • vue3基础,小白从入门到精通
  • 三维算法基础知识
  • Unity Shader:从基础使用到动画实现全解析
  • 二层交换机和三层交换机
  • Vue3+Vue-router(history+路由前缀)+Vite 下本地刷新找不到页面问题
  • 钉钉h5微应用引用钉钉文件地址
  • 解决MYSQL Table has no partition for value from column_list的问题
  • jenkins修改端口以及开机自启
  • Kafka和Jenkins实现EMR上PySpark和EC2上Airflow的CI/CD
  • tcpdump的常见方法
  • Matlab中文注释乱码
  • 力扣编程从0-1