博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
行为型模式:解释器模式
阅读量:3965 次
发布时间:2019-05-24

本文共 10567 字,大约阅读时间需要 35 分钟。

原文首发:

鲨鱼

十一大行为型模式之十:解释器模式。

简介

姓名 :解释器模式

英文名 :Interpreter Pattern
价值观 :不懂解释到你懂​
个人介绍
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
(来自《设计模式之禅》)

你要的故事

解释器顾名思义就是对 2 个不同的表达方式进行转换,让本来不懂的内容解释成看得懂的。比如翻译官就是解释器,把英文翻译成中文,让我们明白外国人说什么。咱们工作中也有很多类似的场景,开发系统避免不了使用数据库,数据库有特定的语法,我们称为 SQL (Structured Query Language),而我们系统开发语言和 SQL 的语法不一样,这中间就需要做一层转换,像把 Java 语言中的 userDao.save(user) 变成 insert into user (name,age) values ('小明', 18),这一层转换也可以称为解释器。很多框架实现了这个功能,比如 Hibernate,我们称这些框架为 ORM

今天,我们就来简单的实现 SQL 拼接解释器,通过参数组装成我们要的 SQL 语句。好多开发同学都吐槽工作天天在 CRUD,也就是只干增删改查的活,对于 SQL 我们经常用的也就是这 4 种语法:insert 语句、delete 语句、update 语句、select 语句。这 4 种语法各有不同,也即需要不同的解释器去解析。利用今天要讲的解释器模式,我们来实现一番。

解释器模式中,会有一个上下文类,这个类用于给解释器传递参数。这里我们 SQL 解释器需要的参数分别是

  1. tableName :数据库名
  2. params :修改时更新后的数据
  3. wheres :where 语句后的条件
class Context {    private String tableName;    private Map
params = new HashMap<>(); private Map
wheres = new HashMap<>(); public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } public Map
getParams() { return params; } public void setParams(Map
params) { this.params = params; } public Map
getWheres() { return wheres; } public void setWheres(Map
wheres) { this.wheres = wheres; }}

解释器主角来了,定义 SQL 解释器抽象类,它有一个抽象方法 interpret,通过这个方法来把 context 中的参数解释成对应的 SQL 语句。

/** * SQL 解释器 */abstract class SQLExpression {    public abstract String interpret(Context context);}

我们上面说了 SQL 语句用的比较多的就是 4 种,每一种其实就是一个解释器,因为语法不一样,解释的逻辑也就不一样,我们就利用 SQLExpression 解释器抽象类,来实现 4 个具体的 SQL 解释器,分别如下:

Insert SQL 解释器代码实现:

/** * Insert SQL 解释器 */class InsertSQLExpression extends SQLExpression {    @Override    public String interpret(Context context) {        StringBuilder insert = new StringBuilder();        insert.append("insert into ")                .append(context.getTableName());        // 解析 key value        StringBuilder keys = new StringBuilder();        StringBuilder values = new StringBuilder();        keys.append("(");        values.append("(");        for (String key : context.getParams().keySet()) {            keys.append(key).append(",");            values.append("'").append(context.getParams().get(key)).append("',");        }        keys = keys.replace(keys.length() - 1, keys.length(), ")");        values = values.replace(values.length() - 1, values.length(), ")");        // 拼接 keys values        insert.append(keys)                .append(" values ")                .append(values);        System.out.println("Insert SQL : " + insert.toString());        return insert.toString();    }}

Update SQL 解释器代码实现:

/** * Update SQL 解释器 */class UpdateSQLExpression extends SQLExpression {    @Override    public String interpret(Context context) {        StringBuilder update = new StringBuilder();        update.append("update ")                .append(context.getTableName())                .append(" set ");        StringBuilder values = new StringBuilder();        for (String key : context.getParams().keySet()) {            values.append(key)                    .append(" = '")                    .append(context.getParams().get(key))                    .append("',");        }        StringBuilder wheres = new StringBuilder();        wheres.append(" 1 = 1 ");        for (String key : context.getWheres().keySet()) {            wheres.append(" and ")                    .append(key)                    .append(" = '")                    .append(context.getWheres().get(key))                    .append("'");        }        update.append(values.substring(0, values.length() - 1))                .append(" where ")                .append(wheres);        System.out.println("Update SQL : " + update.toString());        return update.toString();    }}

Select SQL 解释器代码实现:

/** * Select SQL 解释器 */class SelectSQLExpression extends SQLExpression {    @Override    public String interpret(Context context) {        StringBuilder select = new StringBuilder();        select.append("select * from ")                .append(context.getTableName())                .append(" where ")                .append(" 1 = 1 ");        for (String key : context.getWheres().keySet()) {            select.append(" and ")                    .append(key)                    .append(" = '")                    .append(context.getWheres().get(key))                    .append("'");        }        System.out.println("Select SQL : " + select.toString());        return select.toString();    }}

Delete SQL 解释器代码实现

/** * Delete SQL 解释器 */class DeleteSQLExpression extends SQLExpression {    @Override    public String interpret(Context context) {        StringBuilder delete = new StringBuilder();        delete.append("delete from ")                .append(context.getTableName())                .append(" where ")                .append(" 1 = 1");        for (String key : context.getWheres().keySet()) {            delete.append(" and ")                    .append(key)                    .append(" = '")                    .append(context.getWheres().get(key))                    .append("'");        }        System.out.println("Delete SQL : " + delete.toString());        return delete.toString();    }}

测试代码

public class InterpreterTest {    public static void main(String[] args) {        Context context = new Context();        context.setTableName("user");        // Insert SQL        Map
params = new HashMap<>(); params.put("name", "小明"); params.put("job", "Java 工程师"); context.setParams(params); SQLExpression sqlExpression = new InsertSQLExpression(); String sql = sqlExpression.interpret(context); // Delete SQL Map
wheres = new HashMap<>(); wheres.put("name", "小明"); context.setParams(null); context.setWheres(wheres); sqlExpression = new DeleteSQLExpression(); sql = sqlExpression.interpret(context); // Update SQL params = new HashMap<>(); params.put("job", "Java 高级工程师"); wheres = new HashMap<>(); wheres.put("name", "小明"); context.setParams(params); context.setWheres(wheres); sqlExpression = new UpdateSQLExpression(); sql = sqlExpression.interpret(context); // Select SQL wheres = new HashMap<>(); wheres.put("name", "小明"); context.setParams(null); context.setWheres(wheres); sqlExpression = new SelectSQLExpression(); sql = sqlExpression.interpret(context); }}打印结果:Insert SQL : insert into user(name,job) values ('小明','Java 工程师')Delete SQL : delete from user where 1 = 1 and name = '小明'Update SQL : update user set job = 'Java 高级工程师' where 1 = 1 and name = '小明'Select SQL : select * from user where 1 = 1 and name = '小明'

上面实现了整个解释器模式的代码,其实咱们在开发中,SQL 解析没有这么去实现,更多是用一个工具类把上面的各个 SQL 解释器的逻辑代码分别实现在不同方法中,如下代码所示。因为咱们可以预见的就这 4 种语法类型,基本上不用什么扩展,用一个工具类就足够了。

class SQLUtil {    public static String insert(String tableName, Map
params) { StringBuilder insert = new StringBuilder(); insert.append("insert into ") .append(tableName); // 解析 key value StringBuilder keys = new StringBuilder(); StringBuilder values = new StringBuilder(); keys.append("("); values.append("("); for (String key : params.keySet()) { keys.append(key).append(","); values.append("'").append(params.get(key)).append("',"); } keys = keys.replace(keys.length() - 1, keys.length(), ")"); values = values.replace(values.length() - 1, values.length(), ")"); // 拼接 keys values insert.append(keys) .append(" values ") .append(values); System.out.println("Insert SQL : " + insert.toString()); return insert.toString(); } public static String update(String tableName, Map
params, Map
wheres) { StringBuilder update = new StringBuilder(); update.append("update ") .append(tableName) .append(" set "); StringBuilder values = new StringBuilder(); for (String key : params.keySet()) { values.append(key) .append(" = '") .append(params.get(key)) .append("',"); } StringBuilder wheresStr = new StringBuilder(); wheresStr.append(" 1 = 1 "); for (String key : wheres.keySet()) { wheresStr.append(" and ") .append(key) .append(" = '") .append(wheres.get(key)) .append("'"); } update.append(values.substring(0, values.length() - 1)) .append(" where ") .append(wheresStr); System.out.println("Update SQL : " + update.toString()); return update.toString(); } public static String select(String tableName, Map
wheres) { StringBuilder select = new StringBuilder(); select.append("select * from ") .append(tableName) .append(" where ") .append(" 1 = 1 "); for (String key : wheres.keySet()) { select.append(" and ") .append(key) .append(" = '") .append(wheres.get(key)) .append("'"); } System.out.println("Select SQL : " + select.toString()); return select.toString(); } public static String delete(String tableName, Map
wheres) { StringBuilder delete = new StringBuilder(); delete.append("delete from ") .append(tableName) .append(" where ") .append(" 1 = 1"); for (String key : wheres.keySet()) { delete.append(" and ") .append(key) .append(" = '") .append(wheres.get(key)) .append("'"); } System.out.println("Delete SQL : " + delete.toString()); return delete.toString(); }}

总结

上面用解释器模式实现了 SQL 解释器,然后又指明了实际上咱们开发中大多数是直接一个 SQLUtil 工具类就搞定,并不是说解释器模式没用,想表达的观点是:解释器在工作中很少使用,工作中我们一般遵循的是能用就好策略,满足当前需求,加上一些易扩展性就足够了。解释器模式有比较大的扩展性,就如上面,再加上个建表语句 create table 只需要加一个 CreateTableSQLExpression 就可以轻松实现,不用去改动其他解释器代码。今天的解释器就到讲到这。觉得不错点个赞鼓励鼓励一下。

推荐阅读

转载地址:http://dqkki.baihongyu.com/

你可能感兴趣的文章
Maven配置指南
查看>>
【数据库】:解决无法添加中文数据问题
查看>>
【Intellij IDEA】怎么将IDEA项目文件各级目录完全展示?
查看>>
【Java编程强化练习】-流程控制(1)
查看>>
【Java编程强化练习】-流程控制(2)
查看>>
【Java编程强化练习】-循环条件
查看>>
【DataBase】数据库连接常用数据
查看>>
Attribute names cannot contain colons jdom生成带有名字空间的xml元素
查看>>
在linux用wget直接下载JDK
查看>>
Nicholas C. Zakas:我得到的最佳职业生涯建议
查看>>
在Outlook中如何修改收到邮件的主题 Editing received messages and subjects
查看>>
Oracle的物化视图 MATERIALIZED VIEW
查看>>
文件(夹)名避免使用的字符 Characters to Avoid in Directories and Filenames
查看>>
myeclipse 编辑jsp智能提示 运行慢的解决办法
查看>>
java时间操作函数汇总
查看>>
warning: assignment makes pointer from integer without a cast错误
查看>>
netsh 快速修改IP
查看>>
ThoughtWorks(中国)程序员读书雷达
查看>>
Linux 常用命令集(60个) [ 转贴备忘 ]
查看>>
Struts原理
查看>>