【手写源码-设计模式13】-解释器模式-基于无人机玩漂移场景

1:主题拆解

①基本介绍

②无人机玩漂移

③解释器模式的优缺点

④适用场景

⑤使用实例

2:基本介绍

解释器模式是一种使用频率较低但是学习难度较大的设计模式,用于描述如何使用面向对象语言构成一个简单的语言解释器。某些情况下可能需要自定义一个新语言,这种语言具有自己的文法规则,这时可以使用解释器模式进行设计。

3:无人机玩漂移

无人机作为成人年比较流行的大玩具,如果能够玩出一些新花样,例如玩玩漂移是不是很爽。但是我们在遥控器上进行操作的时候,无人机该执行什么动作呢?今天我们就用玩无人机的熟练程度来研究拆解一下。

1:青铜版

①抽象基类

public abstract class BaseInterpreter
{
    //用于解析遥控器动作与无人机命令
    public abstract void Conversion(Context context);
}

②操作上下文对象

public class Context
{
    private string _Word = null;
    public Context(string word)
    {
        this._Word = word;
    }
    public void Set(string newWord)
    {
        this._Word = newWord;
    }
    public string Get()
    {
        return this._Word;
    }
}

③命令解析

   public class SpeedInterpreter : BaseInterpreter
    {
        private static Dictionary<char, string> _Dictionary = new Dictionary<char, string>();
        static SpeedInterpreter()
        {
            _Dictionary.Add('挪', "move");  
        }
        public override void Conversion(Context context)
        {
            string text = context.Get();
            if (string.IsNullOrEmpty(text))
                return;
            List<string> numberList = new List<string>();
            foreach (var item in text.ToLower().ToArray())
            {
                if (_Dictionary.ContainsKey(item))
                {
                    numberList.Add(_Dictionary[item]);
                }
                else
                {
                    numberList.Add(item.ToString());
                }
            }
            context.Set(string.Join("", numberList));
        }
    }

④上端调用

Console.WriteLine("青铜");
Context context = new Context("挪挪挪挪挪挪挪挪挪");
SpeedInterpreter interpreter = new SpeedInterpreter();
interpreter.Conversion(context);
Console.WriteLine(context.Get());

分析:刚刚开始不会玩的时候,只能慢慢挪动一下。需要借组其中的速度解释器,对主人的动作进行解析。

2:白银版

随着主人熟练程度加深,不用像螃蟹一样总是横着走,现在可以进行调整方向了。

①添加方向解释器

    public class DirectionInterpreter : BaseInterpreter
    {
        private static Dictionary<char, string> _Dictionary = new Dictionary<char, string>();
        static DirectionInterpreter()
        {
            _Dictionary.Add('上', "u");
            _Dictionary.Add('下', "d");
            _Dictionary.Add('左', "l");
            _Dictionary.Add('右', "r"); 
        } 
        public override void Conversion(Context context)
        {
            string text = context.Get();
            if (string.IsNullOrEmpty(text))
                return;
            List<string> numberList = new List<string>();
            foreach (var item in text.ToLower().ToArray())
            {
                if (item == '|')
                {
                    continue;
                }
                if (_Dictionary.ContainsKey(item))
                {
                    numberList.Add(_Dictionary[item]);
                }
                else
                {
                    numberList.Add(item.ToString());
                }
            }
            context.Set(string.Join("|", numberList));
        }
    }

②上端调用

Console.WriteLine("白银");
Context context = new Context("挪上挪左挪右挪下挪");
BaseInterpreter SpeedInterpreter = new SpeedInterpreter();
BaseInterpreter DirectionInterpreter = new DirectionInterpreter();
SpeedInterpreter.Conversion(context);
DirectionInterpreter.Conversion(context);
Console.WriteLine(context.Get());

3:黄金版

继续升级,现在不仅可以上下左右的动,还可以前后运动,此时继续添加解释器

①添加解释器

    public class DirectionInterpreterV2 : BaseInterpreter
    {
        private static Dictionary<char, string> _Dictionary = new Dictionary<char, string>();
        static DirectionInterpreterV2()
        {
            _Dictionary.Add('前', "f");
            _Dictionary.Add('后', "b");
        }
        public override void Conversion(Context context)
        {
            string text = context.Get();
            if (string.IsNullOrEmpty(text))
                return;
            List<string> numberList = new List<string>();
            foreach (var item in text.ToLower().ToArray())
            {
                if (item == '|')
                {
                    continue;
                }
                if (_Dictionary.ContainsKey(item))
                {
                    numberList.Add(_Dictionary[item]);
                }
                else
                {
                    numberList.Add(item.ToString());
                }
            }
            context.Set(string.Join("|", numberList));
        }
    }

②上端调用

Console.WriteLine("黄金");
Context context = new Context("挪上挪左挪右挪下挪前后");
BaseInterpreter SpeedInterpreter = new SpeedInterpreter();
BaseInterpreter DirectionInterpreter = new DirectionInterpreter();
BaseInterpreter DirectionInterpreterV2 = new DirectionInterpreterV2();                    
SpeedInterpreter.Conversion(context);
DirectionInterpreter.Conversion(context);
DirectionInterpreterV2.Conversion(context);
Console.WriteLine(context.Get());

4:铂金版

后面随着速度的提高,主人不在只是挪一下,而是跑起来,飞起来。

①解释器

    public class SpeedInterpreterV2 : BaseInterpreter
    {
        private static Dictionary<char, string> _Dictionary = new Dictionary<char, string>();
        static SpeedInterpreterV2()
        {
            _Dictionary.Add('跑', "r");
            _Dictionary.Add('飞', "f");
        }
        public override void Conversion(Context context)
        {
            string text = context.Get();
            if (string.IsNullOrEmpty(text))
                return;
            List<string> numberList = new List<string>();
            foreach (var item in text.ToLower().ToArray())
            {
                if (item == '|')
                {
                    continue;
                }
                if (_Dictionary.ContainsKey(item))
                {
                    numberList.Add(_Dictionary[item]);
                }
                else
                {
                    numberList.Add(item.ToString());
                }
            }
            context.Set(string.Join("|", numberList));
        }
    }

②上端调用

Console.WriteLine("钻石");
Context context = new Context("挪跑飞上飞左跑右飞下前后跑挪");
BaseInterpreter SpeedInterpreter = new SpeedInterpreter();
BaseInterpreter DirectionInterpreter = new DirectionInterpreter();
BaseInterpreter DirectionInterpreterV2 = new DirectionInterpreterV2();
BaseInterpreter SpeedInterpreterV2 = new SpeedInterpreterV2();
SpeedInterpreter.Conversion(context);
DirectionInterpreter.Conversion(context);
DirectionInterpreterV2.Conversion(context);
SpeedInterpreterV2.Conversion(context);
Console.WriteLine(context.Get());

5:玩漂移了

先说漂移秘诀:前挪跑飞前左上飞左下飞左上飞跑挪

①上端调用

Console.WriteLine("漂移");
Context context = new Context("前挪跑飞前左上飞左下飞左上飞跑挪");
List<BaseInterpreter> interpreterList = new List<BaseInterpreter>()
{
    new SpeedInterpreter(),
    new DirectionInterpreter(),
    new DirectionInterpreterV2(),
    new SpeedInterpreterV2()
};
foreach (var item in interpreterList)
{
    item.Conversion(context);
}  
Console.WriteLine(context.Get());

②输出

分析:从这几个版本的迭代,我们发现解释器的作用就是将遥控器的动作翻译成无人机可以识别的一些命令,进而执行对应的动作。如果需要新增加了一些行为的解析,只需要将解释器的规则进行调整即可。

4:解释器模式的优缺点

1:优点

①扩展性好

由于解释器中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。

②便于实现语言

每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。

③实现文法容易

抽象语法树中每一个表达式节点类的实现方式都是类似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。

④增加解释表达式方便

如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式,原有表达式类无须修改。

2:缺点

①复杂文法难以维护

在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则会导致类个数急增,导致系统难以管理和维护,可以考虑使用语法分析程序来取代解释器模式。

②执行效率低

由于解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时速度很慢,而且代码的调试过程也比较麻烦。

5:适用场景

可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。

一些重复出现的问题可以用一种简单的语言来描述。

一个语言的文法较为简单。

执行效率不是关键问题。

6:使用实例

加密

分词

爬虫写数据

翻译

公式

web开发模版

语法解释器

sql语句解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要迷恋发哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值