一、解释器模式
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用:当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
缺点:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的计数如语法分析程序或编译生成器来处理。
abstract class AbstractExpression { public abstract void Interpret(Context context); } //终结符表达式 class TerminalExpression : AbstractExpression { public override void Interpret(Context context) { Console.WriteLine("终端解释器"); } } //非终结符表达式,对文法中每一条规则都需要一个具体的非终结符表达式类 class NonterminalExpression : AbstractExpression { public override void Interpret(Context context) { Console.WriteLine("非终端解释器"); } }
class Context { private string input; public string Input { get { return input; } set { input = value; } } private string output; public string Output { get { return output; } set { output = value; } } }
static void Main(string[] args) { Context context = new Context(); IList<AbstractExpression> list = new List<AbstractExpression>(); list.Add(new TerminalExpression()); list.Add(new NonterminalExpression()); list.Add(new TerminalExpression()); list.Add(new TerminalExpression()); foreach (AbstractExpression exp in list) { exp.Interpret(context); } Console.Read(); }
二、迭代器模式
提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示,例如foreach。IEumerator支持对非泛型集合的简单迭代接口。
适用:当需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑使用迭代器模式。
关键思想:将对列表的访问和遍历从列表对象中分离处理,并放入一个迭代器对象中,迭代器类定义了一个访问该列表元素的接口。迭代器对象负责跟踪当前的元素,并且知道哪些元素已经遍历过。
abstract class Iterator { //定义开始、下一个、判断结尾、当前对象等抽象方法,统一接口 public abstract object First(); public abstract object Next(); public abstract bool IsDone(); public abstract object CurrentItem(); } class ConcreteIterator : Iterator { //定义了具体聚集对象 private ConcreteAggregate aggregate; private int current = 0; //初始化时将具体的聚集对象传入 public ConcreteIterator(ConcreteAggregate aggregate) { this.aggregate = aggregate; } //得到聚集的第一个对象 public override object First() { return aggregate[0]; } //得到聚集的下一个对象 public override object Next() { object ret = null; current++; if (current < aggregate.Count) { ret = aggregate[current]; } return ret; } //返回当前的聚集对象 public override object CurrentItem() { return aggregate[current]; } //判断当前遍历是否到结尾,到结尾返回true public override bool IsDone() { return current >= aggregate.Count ? true : false; } } class ConcreteIteratorDesc : Iterator { private ConcreteAggregate aggregate; private int current = 0; public ConcreteIteratorDesc(ConcreteAggregate aggregate) { this.aggregate = aggregate; current = aggregate.Count - 1; } public override object First() { return aggregate[aggregate.Count - 1]; } public override object Next() { object ret = null; current--; if (current >= 0) { ret = aggregate[current]; } return ret; } public override object CurrentItem() { return aggregate[current]; } public override bool IsDone() { return current < 0 ? true : false; } }
//创建迭代器 abstract class Aggregate { public abstract Iterator CreateIterator(); } class ConcreteAggregate : Aggregate { //声明一个List泛型变量,用于存放聚合对象 private IList<object> items = new List<object>(); public override Iterator CreateIterator() { return new ConcreteIterator(this); } //返回聚集总个数 public int Count { get { return items.Count; } } //声明一个索引器 public object this[int index] { get { return items[index]; } set { items.Insert(index, value); } } }
static void Main(string[] args) { ConcreteAggregate a = new ConcreteAggregate(); a[0] = "大鸟"; a[1] = "小菜"; a[2] = "行李"; a[3] = "老外"; a[4] = "公交内部员工"; a[5] = "小偷"; Iterator i = new ConcreteIterator(a); object item = i.First(); while (!i.IsDone()) { Console.WriteLine("{0} 请买车票!", i.CurrentItem()); i.Next(); } Console.Read(); }
三、总结
书中最后一个案例主要针对设计思路进行了讲解,比较简单,在实际操作过程中遇到的问题远比此复杂的多。看书多遍只是为了对这些设计模式有一个系统的了解,使用还是需要通过实际的项目来活学活用。
附录B中的书籍可以学习,有些时候书籍出版时间并不代表没有阅读意义,而其涉及的原理是现在依赖开发平台做程序时需要的关键思路。