• 设计模式笔记之十五 (解释器模式)


    解释器模式

    解释器模式就是定义一种语言,并定义这个语言的解释器,解释器能够按照定义好的语法来将这种语言‘翻译’成使用者能理解的语言。

    广泛上来讲,Java是一种定义的语言,JVM就是一种‘解释器’,而计算机就是最终的使用者。我们写一段Java代码,而计算机只认识0101的机器语言,JVM就是将Java代码解释成0101的机器语言让计算机能够理解并运行。

    我们还是以我们实验室的实例来说明下这个模式。

    最近我们实验室的兽人工厂拿到了老总的一个批示:

    class LaoZong {
        private String order = "MN1n2";
    
        public String getOrder() {
            return order;
        }
    
        public void setOrder(String order) {
            this.order = order;
        }
        
    }
    
    class ShouRenFactory {
        public void readOrder() {
            LaoZong lz = new LaoZong();
            System.out.println(lz.getOrder());
        }
    }
    
    public class Interpreter {
        public static void main(String[] args) {
            new ShouRenFactory().readOrder();
        }
    }

     于是兽人工厂拿到老板的指令就是"MN1n2"。完全不明白要干什么,于是需要找老板秘书来解释下:

    class ShouRenFactory {
        public void readOrder() {
            LaoZong lz = new LaoZong();
            MiShu ms = new MiShu();
            
            System.out.println(ms.translate(lz.getOrder()));
        }
    }
    
    class MiShu {
        public String translate(String order) {
            //Black Box
            String realWord = "生产男兽人1个女兽人2个";
            return realWord;
        } 
    }

    现在我们兽人工厂终于知道了老总的命令:"生产男兽人1个女兽人2个", 但是秘书是怎么知道老总的命令的呢,如果兽人工厂也能知道秘书解析的过程,那就不用每次都麻烦秘书来解释了。毕竟秘书是老板用的,而不是兽人工厂用的。

    请教秘书解析的方法:

    秘书说她先判断每一个字幕或者数组是什么类型的命令,然后再用不同的解释方法解释不同的类型,比如说‘M’就是命令类的,‘Nn’是产品名称类的,数字就是数量类的。

    于是兽人工厂就根据秘书的方法实现了自己的解析方式:

    public class Interpreter {
        public static void main(String[] args) {
            new ShouRenFactory().readOrder();
        }
    }
    
    class ShouRenFactory {
        private String translate(String order) {
            String realOrder = "";
            
            //组装解释器
            List<Expression> expressions = new ArrayList<Expression>();
            expressions.add(new CommandExpression());
            expressions.add(new ProductExpression());
            expressions.add(new NumberExpression());
            
            //挨个解释老总的命令
            String[] codes = order.split("");
            for (String code :codes) {
                for (Expression expression : expressions) {
                    if (expression.matches(code)) {
                        realOrder += expression.excute(code);
                        break;
                    }
                }
            }
            
            return realOrder;
        }
        public void readOrder() {
            LaoZong lz = new LaoZong();
    
            System.out.println(translate(lz.getOrder()));
        }
    }
    
    abstract class Expression {
        protected HashMap<String, String> map = new HashMap<String, String>();
    
        private Set<String> getMarkers() {
            return map.keySet();
        }
    
        public boolean matches(String code) {
            return getMarkers().contains(code);
        }
    
        abstract public String excute(String code);
    }
    
    class CommandExpression extends Expression {
    
        public CommandExpression() {
            map.put("M", "创建");
            map.put("D", "销毁");
            map.put("E", "维修");
        }
    
        @Override
        public String excute(String code) {
            return map.get(code);
        }
    }
    
    class ProductExpression extends Expression {
    
        public ProductExpression() {
            map.put("N", "男兽人");
            map.put("n", "女兽人");
        }
    
        @Override
        public String excute(String code) {
            return map.get(code);
        }
    }
    
    class NumberExpression extends Expression {
    
        public NumberExpression() {
        }
    
        @Override
        public boolean matches(String code) {
            return code.matches("[0-9]");
        }
        
        @Override
        public String excute(String code) {
            return code + "个";
        }
    }

    这样我们就实现了一个简单的解析器模式,在这种模式下,我们可以很简单的增加或者删除某种解析器。

    解析器模式是一种易于理解但难于应用的模式。 除非在“一种特定类型的问题发生的频率足够高”的情况下,我们并不推荐使用此模式。因为当文法特别复杂时,会产生很多类,这对维护来说比较困难。总的来说在文法比较简单且发生频率很高的情况下才使用此模式。

  • 相关阅读:
    深入浅出Blazor webassembly之程序配置
    深入浅出Blazor webassembly之通过CascadingValue组件实现向子级组件传值
    深入浅出Blazor webassembly之数据绑定写法
    深入浅出Blazor webassembly之浏览器WSAM性能测试
    重构的秘诀:消除重复,清晰意图
    在多数据源中对部分数据表使用shardingsphere进行分库分表
    logstach http input
    Addax 备忘
    WIN10下面0x00000bcb共享打印机无法连接怎么办?
    Calcite(二): 从list到tree的转换1
  • 原文地址:https://www.cnblogs.com/biglaojiang/p/3337190.html
Copyright © 2020-2023  润新知