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

【设计模式】设计模式之解释器模式

文章目录

  • 前言
  • 一、解释器模式
  • 二、最佳实践
  • 总结

前言

本节给大家讲一下设计模式中的解释器模式,并结合实际业务场景给大家讲解如何使用~

所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整~

一、解释器模式

解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的语法表示,并定义了一个解释器来解释这种语言中的表达式。

通过使用解释器模式,可以轻松地扩展和修改语言的语法,从而使其更加灵活。

该模式的结构包含以下组件:

  • 抽象表达式(AbstractExpression):定义了一个解释器中的抽象操作,每个具体的解释器都实现了该抽象操作。
  • 终结符表达式(TerminalExpression):定义了一个解释器中的终止操作,它不能再进行解释。
  • 非终结符表达式(NonterminalExpression):定义了一个解释器中的非终止操作,它可以递归调用其他解释器进行解释。
  • 环境(Context):保存了解释器需要的一些全局信息。

下面我们举一个大家日常开发中最常用的定时任务的例子:

// 抽象表达式
// 抽象表达式接口
public interface Expression {boolean interpret(String expression);
}// 秒表达式
public class SecondExpression implements Expression {@Overridepublic boolean interpret(String expression) {// 解析表达式,判断秒数是否匹配return true; // 返回是否匹配}
}// 分钟表达式
public class MinuteExpression implements Expression {@Overridepublic boolean interpret(String expression) {// 解析表达式,判断分钟数是否匹配return true; // 返回是否匹配}
}// 小时表达式
public class HourExpression implements Expression {@Overridepublic boolean interpret(String expression) {// 解析表达式,判断小时数是否匹配return true; // 返回是否匹配}
}// 日表达式
public class DayOfMonthExpression implements Expression {@Overridepublic boolean interpret(String expression) {// 解析表达式,判断日期是否匹配return true; // 返回是否匹配}
}// 定时任务表达式
public class CronExpression implements Expression {private Expression secondExpression;private Expression minuteExpression;private Expression hourExpression;private Expression dayOfMonthExpression;public CronExpression(Expression secondExpression, Expression minuteExpression,Expression hourExpression, Expression dayOfMonthExpression) {this.secondExpression = secondExpression;this.minuteExpression = minuteExpression;this.hourExpression = hourExpression;this.dayOfMonthExpression = dayOfMonthExpression;}@Overridepublic boolean interpret(String expression) {String[] fields = expression.split(" ");// 解析定时任务表达式,判断各个字段是否匹配boolean matchSecond = secondExpression.interpret(fields[0]);boolean matchMinute = minuteExpression.interpret(fields[1]);boolean matchHour = hourExpression.interpret(fields[2]);boolean matchDayOfMonth = dayOfMonthExpression.interpret(fields[3]);return matchSecond && matchMinute && matchHour && matchDayOfMonth;}
}public class Client {public static void main(String[] args) {// 创建表达式对象Expression second = new SecondExpression();Expression minute = new MinuteExpression();Expression hour = new HourExpression();Expression dayOfMonth = new DayOfMonthExpression();Expression cron = new CronExpression(second, minute, hour, dayOfMonth);// 判断定时任务是否应该被执行String expression = "0 0 1 * *"; // 每月1日执行任务boolean match = cron.interpret(expression);if (match) {System.out.println("定时任务执行中...");} else {System.out.println("定时任务未开始...");}}
}

当定时任务表达式为0 0 1 * *时,表示该定时任务在每个月的1日执行。如果当前日期是1日,那么match变量的值将为true,表示该定时任务应该被执行。否则,match变量的值将为false,表示该定时任务还未开始执行。表达式内部具体规则逻辑可以自行实现,这里只是为了方便演示~

二、最佳实践

在电商平台中,可以使用解释器模式来实现一个基于规则的折扣系统。该系统可以根据用户的购物车内容和优惠规则来计算出最终的折扣金额。

下面是一个示例,展示了如何使用解释器模式来实现一个基于规则的折扣系统:

// 抽象表达式
interface DiscountExpression {double interpret(ShoppingCart cart);
}// 终结符表达式:商品价格
class ItemPrice implements DiscountExpression {private String itemId;public ItemPrice(String itemId) {this.itemId = itemId;}public double interpret(ShoppingCart cart) {double price = 0;for (CartItem item : cart.getItems()) {if (item.getItemId().equals(itemId)) {price += item.getPrice() * item.getQuantity();}}return price;}
}// 终结符表达式:折扣价格
public class DiscountPrice implements  DiscountExpression {private double discount;public DiscountPrice(double discount) {this.discount = discount;}@Overridepublic double interpret(ShoppingCart cart) {double price = 0;for (CartItem item : cart.getItems()) {price += item.getPrice() * item.getQuantity() * discount;}return price;}
}// 终结符表达式:购物车总价
class CartTotal implements DiscountExpression {public double interpret(ShoppingCart cart) {double total = 0;for (CartItem item : cart.getItems()) {total += item.getPrice() * item.getQuantity();}return total;}
}// 非终结符表达式:满减
class Discount implements DiscountExpression {private DiscountExpression condition;private DiscountExpression action;public Discount(DiscountExpression condition, DiscountExpression action) {this.condition = condition;this.action = action;}public double interpret(ShoppingCart cart) {if (condition.interpret(cart) > 0) {return action.interpret(cart);}return 0;}
}// 环境:购物车
class ShoppingCart {private List<CartItem> items;public ShoppingCart() {items = new ArrayList<>();}public void addItem(CartItem item) {items.add(item);}public List<CartItem> getItems() {return items;}
}// 环境:购物车商品项
class CartItem {private String itemId;private String itemName;private double price;private int quantity;public CartItem(String itemId, String itemName, double price, int quantity) {this.itemId = itemId;this.itemName = itemName;this.price = price;this.quantity = quantity;}public String getItemId() {return itemId;}public String getItemName() {return itemName;}public double getPrice() {return price;}public int getQuantity() {return quantity;}
}// 客户端
public class DiscountSystemDemo {public static void main(String[] args) {// 初始化购物车ShoppingCart cart = new ShoppingCart();cart.addItem(new CartItem("001", "商品1", 100, 2));cart.addItem(new CartItem("002", "商品2", 200, 1));// 定义折扣规则DiscountExpression rule1 = new Discount(new ItemPrice("001"), new DiscountPrice(0.1));DiscountExpression rule2 = new Discount(new ItemPrice("002"), new DiscountPrice(0.2));// 计算折扣double discount1 = rule1.interpret(cart);double discount2 = rule2.interpret(cart);double totalDiscount = discount1 + discount2;// 输出结果System.out.println("折扣总额:" + totalDiscount);System.out.println("应付金额:" + (new CartTotal().interpret(cart) - totalDiscount));//        折扣总额:120.0
//        应付金额:280.0}
}

上述仅仅是一个简单的示例,实际应用中可能会更加复杂。例如,可能需要实现更多的折扣规则类型,或者添加更多的操作和函数。但是,无论怎样扩展和修改折扣系统的规则,解释器模式都可以帮助我们轻松地完成这些任务。

总结

解释器模式其实并不难,大家在学习的时候一定要在理解的基础上去写代码,不要去背代码。

相关文章:

【设计模式】设计模式之解释器模式

文章目录 前言一、解释器模式二、最佳实践总结 前言 本节给大家讲一下设计模式中的解释器模式,并结合实际业务场景给大家讲解如何使用~ 所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整~ 一、解释器模式 解释器模式&#xff08;Interpreter Pattern&#xff09;…...

leetcode551. 学生出勤记录 I

题目描述解题思路执行结果 leetcode551. 学生出勤记录 I . 题目描述 给你一个字符串 s 表示一个学生的出勤记录&#xff0c;其中的每个字符用来标记当天的出勤情况&#xff08;缺勤、迟到、到场&#xff09;。记录中只含下面三种字符&#xff1a; A&#xff1a;Absent&#xff…...

flume拦截器介绍

Flume是一个开源的、分布式的、可靠的、高效的海量数据采集、聚合和传输系统。其中&#xff0c;拦截器(Interceptor)是Flume中的一种组件&#xff0c;可以在数据(Event)流动的各个阶段对数据进行处理、过滤或转换&#xff0c;从而实现更为灵活、高效的数据采集和传输。 1、拦截…...

5.4、服务器编程基本框架和两种高效的事件处理模式

5.4、服务器编程基本框架和两种高效的事件处理模式 1.服务器编程基本框架2.两种高效的事件处理模式①Reactor模式②Proactor模式③模拟Proactor模式 1.服务器编程基本框架 模块功能I/O 处理单元处理客户连接&#xff0c;读写网络数据逻辑单元业务进程或线程网络存储单元数据库、…...

Flink主要有两种基础类型的状态:operator state。

Flink主要有两种基础类型的状态&#xff1a;keyed state 和operator state。 Operator State 对于Operator State(或者non-keyed state)&#xff0c;每个operator state绑定到一个并行operator实例上。在Flink中&#xff0c;Kafka Connector是一个使用Operator State的很好的例…...

【vue2】使用vue-admin-template动态添加路由的思路/addRoutes的使用

&#x1f609;博主&#xff1a;初映CY的前说(前端领域) ,&#x1f4d2;本文核心&#xff1a;用原生js实现省市区联动 【前言】在通用的后台管理项目的开发中&#xff0c;不仅仅是会涉及到对表单数据等的增删改查操作还会涉及到一些关于权限管理的问题。我们将基于一个RBAC的思维…...

Python语言中的注释方法应用

Python语言中的注释方法 在Python编程中&#xff0c;与其他编程语言一样&#xff0c;有良好的注释部分&#xff0c;会让你的程序在后续的改进或优化中&#xff0c;变得便利。同时&#xff0c;给自己培养了良好的编程习惯。 在Python语言中&#xff0c;有两种注释方法。 1.单行…...

Google浏览器翻译无法正常使用解决

1.查找可用服务器地址 按WinR键打开运行→输入cmd回车&#xff0c;打开命令提示符→输入ping google.cn 回车。记录一下下图红框里的ip地址&#xff0c;一会要用到 最近自己ping出来的ip可能不能用了&#xff0c;可以尝试用下面的ip 142.251.163.90 142.250.113.90 142.251.…...

ETCD(三)操作指令

1. put put #将给定的key写入到存储 --ignore-lease[false] #使用当前租约更新key --ignore-value[false] #使用当前值更新key --lease"0" # 要附加到key的租约ID&#xff08;十六进制&#xff09; --prev-kv[false] # 返回修改前的上一个键值对2. get get #获取给…...

小白学Pytorch系列--Torch.optim API Base class(1)

小白学Pytorch系列–Torch.optim API Base class(1) torch.optim是一个实现各种优化算法的包。大多数常用的方法都已得到支持&#xff0c;而且接口足够通用&#xff0c;因此将来还可以轻松集成更复杂的方法。 如何使用优化器 使用手torch.optim您必须构造一个优化器对象&…...

flac格式如何转mp3,3招帮你搞定

flac格式如何转mp3&#xff0c;3招帮你搞定的方法来啦。当你的音频是flac格式是不是很头疼&#xff0c;又不知道怎么转mp3 。然后网上搜索出很多方法又不知道从哪个下手&#xff0c;是不是很疑惑&#xff1f;那今天就来看看小编推荐的方法吧&#xff0c;一定让你眼前一亮&#…...

Redis入门到入土(day01)

NoSQL概述 为什么用NoSQL 1、单机MySQL的美好年代 在90年代&#xff0c;一个网站的访问量一般不大&#xff0c;用单个数据库完全可以轻松应付&#xff01; 在那个时候&#xff0c;更多的都是静态网页&#xff0c;动态交互类型的网站不多。 上述架构下&#xff0c;我们来看看…...

JVM垃圾回收GC 详解(java1.8)

目录 垃圾判断算法&#xff08;你是不是垃圾&#xff1f;&#xff09; 引用计数法 可达性算法 对象的引用 强引用 软引用 弱引用 虚引用 对象的自我救赎 垃圾回收算法--分代 标记清除算法 复制算法 标记整理法 垃圾处理器 垃圾判断算法&#xff08;你是不是垃圾&…...

Mybatis-Plus -03 Mybatis-Plus实现CRUD

Mybatis-Plus实现CRUD 1 Insert增加2 ID生成策略3 Delete删除4 逻辑删除5 Update修改6 Select查询 Mybatis-Plus实现CRUD 通用 CRUD 封装**BaseMapper (opens new window)**接口&#xff0c;为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器参数 …...

综合能源系统中基于电转气和碳捕集系统的热电联产建模与优化研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

“智慧赋能 强链塑链”|工程物资供应链管理中的数字化应用

工程项目中的供应链管理至关重要 工程建设行业是国民经济的重要支柱之一&#xff0c;虽然在总产值上持续保持增长态势&#xff0c;但近年来行业的利润总额增速已连续多年呈现下降趋势。究其原因&#xff0c;可以大体从两个方面来看&#xff1a;一是行业盈利能力出现下降&#x…...

通过docker发布项目

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言例如&#xff1a;docker项目的发布方式 [docker发布的参考链接](https://www.cnblogs.com/emperorking/articles/11244253.html) 一、docker是什么&#xff1f;…...

为什么Spring和IDEA不推荐使用@Autowired注解?

在Spring开发中&#xff0c;Autowired注解是一个常用的依赖注入方式。但是&#xff0c;你可能会惊奇地发现&#xff0c;Spring和IDEA都不推荐使用Autowired注解。关于这个问题&#xff0c;其实答案相对统一&#xff0c;实际上用大白话说起来也容易理解。 官方答案 首先&#…...

windows下运行dpdk下的helloworld

打开“本地安全策略”管理单元,在搜索框输入secpol。 打开本地策略->用户权限分配->锁定内存页->添加用户或组->高级->立即查找 输入电脑用户名,选择并添加。点击确定后,重启电脑。 安装内核驱动,下载地址https://download.csdn.net/download/qq_36314864…...

【AI理论学习】深入理解Prompt Learning和Prompt Tuning

深入理解Prompt Learning和Prompt Tuning 背景Prompt Learning简介1. Prompt是什么&#xff1f;2. 为什么要使用Prompt&#xff1f;3. Prompt Learning的形式&#xff08;举例&#xff09;4. 有哪些Pre-training language model&#xff1f;5. 常见的Prompt Learning的方法 Pro…...

从Authy中导出账户和secret

本文转载于我的博客从Authy中导出账户和secret 前言 因为最近买了CanoKey&#xff0c;所以多算试一下CanoKey的TOTP功能&#xff0c;但是之前一直用的Authy并且它默认不支持导出功能 在网上找了一些文档&#xff0c;终于在github上找到了一个有效且简单的方法 目前网上大部分…...

图像锐度评分算法,方差,点锐度法,差分法,梯度法

图像锐度评分算法&#xff0c;方差&#xff0c;点锐度法&#xff0c;差分法&#xff0c;梯度法 图像锐度评分是用来描述图像清晰度的一个指标。常见的图像锐度评分算法包括方差法、点锐度法、差分法和梯度法等。 方差法&#xff1a;该方法是通过计算图像像素值的方差来评估图像…...

查询练习:连接查询

准备用于测试连接查询的数据&#xff1a; CREATE DATABASE testJoin;CREATE TABLE person (id INT,name VARCHAR(20),cardId INT );CREATE TABLE card (id INT,name VARCHAR(20) );INSERT INTO card VALUES (1, 饭卡), (2, 建行卡), (3, 农行卡), (4, 工商卡), (5, 邮政卡); S…...

【mmdeploy】【TODO】使用mmdeploy将mmdetection模型转tensorrt

mmdetection转换 文章目录 mmdetection转换mmdetection 自带转换ONNX——无法测试使用mmdeploy(0.6.0)使用mmdeploy转onnx使用mmdeploy直接转tensorRT调试记录 先上结论&#xff1a;作者最后是转tensorrt的小图才成功的&#xff0c;大图一直不行。文章仅作者自我记录使用&#…...

德赛西威上海车展重磅发布Smart Solution 2.0,有哪些革新点?

4月18日&#xff0c;全球瞩目的第二十届上海车展盛大启幕&#xff0c;作为国际领先的移动出行科技公司&#xff0c;德赛西威携智慧出行黑科技产品矩阵亮相&#xff0c;并以“智出行 共创享”为主题&#xff0c;重磅发布最新迭代的智慧出行解决方案——Smart Solution 2.0。 从…...

戴尔服务器是否需要开启cpupower.service

戴尔并不会默认开启cpupower.service&#xff0c;这取决于具体的操作系统和配置。cpupower.service是一个Linux系统服务&#xff0c;用于管理CPU的功耗和性能调节&#xff0c;可以通过调整CPU的频率和电源管理策略来降低能耗和温度。在某些情况下&#xff0c;开启cpupower.serv…...

day02_第一个Java程序

在开发第一个Java程序之前&#xff0c;我们必须对计算机的一些基础知识进行了解。 常用DOS命令 Java语言的初学者&#xff0c;学习一些DOS命令&#xff0c;会非常有帮助。DOS是一个早期的操作系统&#xff0c;现在已经被Windows系统取代&#xff0c;对于我们开发人员&#xf…...

【华为OD机试真题 】1011 - 第K个排列 (JAVA C++ Python JS) | 机试题+算法思路+考点+代码解析

文章目录 一、题目🔸题目描述🔸输入输出🔸样例1🔸样例2二、代码参考🔸C++代码🔸Java代码🔸Python代码🔸JS代码作者:KJ.JK🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🍂个人博客首页: KJ.JK 💖系列专栏:...

基于php的校园校园兼职网站的设计与实现

摘要 近年来&#xff0c;信息技术在大学校园中得到了广泛的应用&#xff0c;主要体现在两个方面&#xff1a;一是学校管理系统&#xff0c;包括教务管理、行政管理和分校管理&#xff0c;是我国大学管理和信息传递的主要渠道。二是学生生活服务平台。而随着大学生毕业人数的年…...

django部署

1. 配置服务器 安装django&#xff0c;python等服务–尽量和你的自己的配置相同&#xff0c;一摸一样避免出现问题 2.django项目迁移 sudo scp /home/tarena/django/mysitel root88.77.66.55:/home/root/xxx #然后输入密码3&#xff0c;用uWSGI 替代python manage.py runse…...