• 设计模式问答(二)


    什么是解释器模式?

    解释器模式同意将语义解释到代码解决方式中。

    以下让我们来了解详细含义?语法是映射到类中来应用到解决方式中。比如7-2能够映射到‘clsMinus’类。

    在第一行解释器模式给我们提供了一种怎样编写解释器的方案。该方案中解释器能够读取并在代码中运行该语法。

    比如以下样例中我们给出了一个日期格式化语法,当中解释器给出了转换的代码解决方式并输出期望结果。


    图1:日期语法

    让我们来写一个如图“日期语法”中所看到的的日期格式化解释器。在開始之前我们须要理解解释器模式中不同组件。之后我们将映射同样的语法。Context包括数据。逻辑部分包括将context转换为可读格式的逻辑。


    图2:上下文及逻辑

    接下来我们看看日期格式化中的语法。在定义不论什么语法之前。我们首先要把语法拆分为小的逻辑块。图“语法映射到类”展示了不同组件是怎样确定的。然后映射到类的语法仅仅是实现了完整语法中的一部分。这样我们将日期格式化拆分为4个组件月、日、年以及分隔符;对这四个组件我们定义了不同的类来包括各自的逻辑,如图“语法映射到类”中所看到的。因此,我们将为日期格式化中4个不同的组件创建不同的类。


    图3:语法映射到类

    如前所述,有两个类当中一个是表达式类,该类包括逻辑;还有一个是上下文类(context),该类包括数据,如图“表达式和上下文类”所看到的。我们将不同的解析定义在不同的类中,全部这些类都继承自‘ClsAbstractExpression’接口。该接口包括‘Evaluate’方法;当中‘Evaluate’方法持有一个包括有数据的上下文类,而且通过表达式逻辑来解析数据。比如‘ClsYearExpression’会将‘YYYY’替换为年份,’ClsMonthExpression’将‘MM’替换为月份等等。


    图4:解释器模式类图


    图5:表达式和上下文类

    至此我们已经将表达式解析逻辑封装在了不同的类中,如今我们来看下client使用逻辑。

    client首先传递日期格式化语法到上下文类;依据日期格式化我们加入表示类到一个集合中。比如当发现“DD”表达式时会添加‘ClsDayExpression’。遇到‘MM’表达式时则会加入‘ClsMonthExpression’类,等等。终于我们循环调用这些类的‘Evaluate’方法。

    当全部类都被调用后我们就得到了显示结果。


    图6:client效用解释器代码逻辑

    什么是迭代器模式?

    迭代器模式同意在不暴露内部代码的情况下顺序存取元素。详细含义例如以下。

    如果有一个记录的集合,我们想顺序性浏览这些结合同一时候还想保存当前已经浏览的记录的位置,那么迭代器模式就是我们所须要的。该模式是最常见且常常无意中使用的模式。在全部使用‘foreach’(同意顺序性循环一个集合)循环的地方我们就在一定程度上在使用迭代器模式了。


    图7:迭代器模式业务逻辑

    在图“迭代器模式业务逻辑”中我们定义了一个包括客户类集合的类‘clsIterator’。因此我们我们首先在‘clsIterator’中定义了一个ArrayList以及一个‘FillObjects’方法来为ArrayList填充数据。

    这个消费者集合ArrayList是私有的(private)。而且客户数据能够通过集合中的下标来查找。因此我们开放了‘getByIndex’方法(通过指定下标来查找元素)、‘Prev’方法(获得集合中前一个元素)、‘Next’方法(获取集合中下一个元素)、‘getFirst’方法(获取结合中第一个元素)、‘getLast’方法(获取集合中最后一个元素)。

    client仅仅能看到这些方法,通过这些函数来顺序訪问集合而且能够记住已经訪问过的下标。

    下图“client使用迭代器模式逻辑”展示了怎样使用‘clsIterator’中next、previous、last、first函数以及指定下标来创建‘ObjIterator’对象的。


    图8:client使用迭代器模式逻辑

    什么是调停者模式?

    非常多时候项目中组件之间的通信是非常复杂的,由于组件之间的相互调用而变的复杂。

    调停者模式帮助对象以没有关联的方式来通信,这使得复杂度最小化。


    图9:调停者模式简单样例

    让我们考虑上图“调停者模式简单样例”中的情况,该图描写叙述了一个真实场景中须要调停者模式的情况。它是一个很常使用户友好的接口;它有3中典型场景:

    场景1:当用户在文本框中输入文字后须要开启添加button以及清空button。在这个样例中文本框中为空。此时须要禁用添加和清空button。


    图10:场景1

    场景2:当用户点击加入button时数据应该进入到列表框中。

    一旦输入内容进入列表框,系统须要清空文本框并禁用添加和清除button。


    图11:场景2

    场景3:假设用户点击清除button系统应该清空文本框并禁用添加和清除button。


    图12:场景3

    从上图场景3中UI界面能够看出这些UI之间的交互是多么复杂。下图“组件之间的复杂交互”展示了逻辑的复杂性。


    图13:组件之间的复杂交互

    接着我们来看下图“调停者使用简化图”。

    各个组件之间并非直接交互,而是都与一个中心化组件如调停者交互,由调停者来关注发送信息至其它组件。这样逻辑将变的干净清晰。


    图14:调停者使用简化图

    以下我们看看代码是怎样写的。我们将使用C#可是大家也能够非常easy的将其转换为java代码或者其它语言。下图“调停者类”展示的调停者类的完整代码。

    调停者类首先做的事情就是持有复杂交互相关类的引用。

    所以这里我们开放3个名为‘Register’的重载方法。‘Register’持有文本框对象和button对象。场景的交互被集中在‘ClickAddButton’、’TextChange’、‘ClickClearButton’方法中。这些方法将依据不同场景启用和禁用相关UI。


    图15:调停者类

    同一时候client代码很整洁。在构造函数中首先注冊全部须要和调停者类交互的组件;接着对于每一个场景仅仅须要调用调停者类的方法就可以。简而言之。当文本发生变化时我们调用调停者类的‘TextChange’方法,当用户点击加入button时调用‘ClickAddButton’方法。当用户点击清空button时调用‘ClickClearButton’方法。


    图16:调停者模式client逻辑

    什么是备忘录模式?

    备忘录模式是提供一种在不破坏封装的情况下提供捕获对象内部状态的方式。

    它有助于存储对象的快照以便不论什么时候查询。以下我们来了解它在实际场景中的含义。

    下图“备忘录模式实践样例”中展示的了一个客户屏幕。如果用户開始编辑一条客户记录并作出一些改动;过了一会以后该用户认为操作有误想要恢复到原始数据,这就是备忘录模式的适用场景。它帮助我们存储一份数据的拷贝并在用户点击取消时恢复到原始状态。


    图17:备忘录模式实践样例

    以下我们来尝试使用C#完毕我们刚刚讨论的客户UI的样例。以下是客户类‘clsCustomer’,该类聚合了存储数据快照的备忘录类‘clsCustomerMemento’。当中备忘录类‘clsCustomerMemento’是明白用来复制客户类(不包含方法)‘clsCustomer’;当消费者类‘clsCustomer’初始化时,备忘录类也跟着初始化。当客户类数据发生改变时。备忘录类中的快照未发生变化。当中‘Revert’方法能够将备忘录中的数据恢复到main类中。


    图18:备忘录中的客户类

    client代码很easy。

    创建客户类,一旦有问题我们能够点击取消button来调用‘revert’方法将数据恢复至备忘录中的快照数据。

    图“备忘录client代码”图中展示了该逻辑。


    图19:备忘录client代码

    什么是观察者模式?

    观察者模式帮助我们完毕父类和与他相关或依赖的类之间的通信。

    当中有两个比較重要的概念‘Subject’(主题)和‘Observers’(观察者)。

    主题(subject)发送通知后,假设观察者注冊到该主题,则会收到通知。

    下图“subject和observers”展示了应用(主题)发送通知到全部观察者(email、事件日志、SMS)。我们也能够将这个样例封装成公布/订阅模型。公布者就是应用。订阅者就是email、事件日志、sms。


    图20:subject和observers

    接下来我们尝试我们在前一小节中定义的简单演示样例代码。首先。我们先看看订阅者/通知类。图“订阅者类”展示了该代码,当中为全部订阅者定义了统一接口如‘INotification’,该接口有一个‘notify’方法。这个接口被全部详细的通知类实现。全部通知类定义自己的通知方法。

    对当前的场景来说我们仅仅是显示一个打印字符串来表示某个特定方法被运行。


    图21:订阅者类

    如前所看到的,观察者模式中分为两个部分,一个是观察者/订阅者,如前边我们提到的一样。还有一个是公布者或者主题。

    公布者有一个集合来存放全部须要收到通知的订阅者。通过使用‘addNotification’和‘removeNotification’能够从集合中添加或删除订阅者;使用‘NotifyAll’方法循环全部订阅者来发送通知。


    图22:公布者/主题类

    至此我们已经了解了公布致和订阅者类,以下让我们来些client代码并看看观察者表现。

    以下是一个观察者客户机代码片段。首先创建一个拥有订阅者集合的通知者对象。接着将须要被通知的订阅者加入到结合中。此时的逻辑是假设客户的代码长度超过10个字符时通知全部订阅者。


    图24:观察者模式client代码



    1. 本文由程序猿学架构翻译

    2. 本文译自

    http://www.codeproject.com/Articles/28359/Design-pattern-FAQ-Part-Design-pattern-training

    3. 转载请务必注明本文出自:程序猿学架构(微信号:archleaner )

    4. 很多其它文章请扫码:

  • 相关阅读:
    ASP.NET MVC随想录——锋利的KATANA
    ASP.NET MVC随想录——漫谈OWIN
    Notepad++ 64位 插件管理
    C#实现按键精灵的'找图' '找色' '找字'的功能
    http://www.haolizi.net/example/view_2380.html
    C# 关于在原图中寻找子图片坐标的类
    WebBrowser控件默认使用IE9,IE10的方法
    Springboot---后台导出功能,easyExcel
    vue---EleElement UI 表格导出功能
    vue---提取公共方法
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6758979.html
Copyright © 2020-2023  润新知