随笔分类 - 设计模式
摘要:Builder模式也可以造车。 对于Builder模式来说,首相要把要造的车确定下来: public class Car { public string Model { get; set; } public string Engine { get; set; } public string Transmission { get; ...
阅读全文
摘要:可以用抽象工厂模式来造车。 车的品牌有很多,而且车的属性也不少,比如车的类型、排量、门的数量,等等。可以提炼出有关车的一个抽象类: public abstract class Car { public string Model { get; set; } public string Engine { get; set; } ...
阅读全文
摘要:本篇体验使用C#的泛型队列Queue实现生产消费模式。 如果把生产消费想像成自动流水生产线的话,生产就是流水线的物料,消费就是某种设备对物料进行加工的行为,流水线就是队列。 现在,要写一个体现生产消费模式的泛型帮助类,比如叫ProducerConsumer。 该类肯定会维护一个有关生产、物料的Queue类型的字段,还存在一个有关消费、Action类型的字段。 在Producer...
阅读全文
摘要:最近踢了场球,9人制比赛,上半场我们采用防守阵型效果不佳,下半场采用进攻阵型取得了比赛的主动。我们上下半场所采取的策略,似乎可以用"装饰器"模式实现一遍。 首先肯定是抽象基类。 public abstract class OurStrategy { public abstract void Play(string msg); } 通常,在上半场,我...
阅读全文
摘要:设计嵌套评论数据库表可仿效无限级分类,在表中加一个ParentId字段。嵌套评论页面大致这样: 评论1 回复评论1 恢复评论1评论2 回复评论2 评论3...... 但是, 在显示评论的时候,如果使用ParentId会涉及到多表的联结,嵌套层级越多意味着表之间的联结增多,这样会影响查询效率。 于是,我们想到在表中增加一个字段,用来显示所有的层级:/1/2/5/ 设计...
阅读全文
摘要:在"实现观察者模式(Observer Pattern)的2种方式"中,曾经通过接口的方式、委托与事件的方式实现过观察者模式。本篇体验使用Action实现此模式,并从中体验委托与事件的区别。 □ 使用Action实现观察者模式 就举一个足球场上的例子,当裁判吹响终场哨,胜队庆祝,失败队落寞。把裁判看作是被观察者,比赛中的两队看作是观察者。 裁判作为被观察者需要提供一个Action委托供观...
阅读全文
摘要:在观察者模式中有2个要素:一个是被观察对象,另一个是观察者。但被观察对象的状态发生改变会通知观察者。 举例:把订阅报纸的人看作是观察者,把报纸看作被观察对象。每当有新的新闻就要通知订阅报纸的人。本篇分别用实现接口和使用委托事件的方式来实现。 □ 通过实现接口实现 观察者接口,把接收到的新闻显示出来。 public interface IObserver { v...
阅读全文
摘要:需要记录日志的地方包括:进入方法的时候,传参的时候,统计执行时间,方法返回参数的时候,退出语句块的时候,出现异常的时候,等等。先来体验不使用Micirosoft Unity进行日志记录。 class Program { static void Main(string[] args) { Add(1, 2); Co...
阅读全文
摘要:简单来说,备忘录模式就是支持回退操作。假设让一个Notepad支持回退操作,如何实现呢? 首先需要一个备忘录类。 public class Memento { private string _msg; public Memento(string msg) { _msg = msg; } publ...
阅读全文
摘要:在显示树形结构时,复合模式有很好的体现。本篇显示如下部门结构: 以上,有的节点包含子节点,有的节点部包含子节点。不管是什么节点,每个节点就代表一个部门。 首先设计一个关于部门的抽象基类。 public abstract class DepartmentComponent { public string Name { private set; get; } ...
阅读全文
摘要:假设要做一道红烧肉,做法有很多,在不同的做法中都有相同的部分,比如都要放油、放肉、放调料等。也有不同之处,比如有些做法放可乐,有些做法放甜蜜酱,等等。 先提炼出一个抽象类,该类不仅有制作红烧肉的各个步骤,而且还把各个步骤归纳到另一个方法,我们把这个方法称作模版方法。另外,在模版方法中,对于一些不确定的方面先用抽象方法。 public abstract class HongShaoRou ...
阅读全文
摘要:假设想让遥控器控制电灯的开关、电视机的开关和切换,该如何做? 所有的开、关、切换都是遥控器发出的指令,把这些指令统一抽象成一个接口。 public interface IControl { void Execute(); }把电灯、电视机抽象成类。 public class Tv { public void TurnOn() ...
阅读全文
摘要:假设有一个公司要做产品套餐,即把不同的产品组合在一起,不同的组合对应不同的价格。最终呈现出来的效果是:把产品组合的所有元素呈现出来,并显示该组合的价格。 每个产品都有名称和价格,首先设计一个关于产品的抽象基类。 public abstract class ProductBase { public abstract string GetName(); pub...
阅读全文
摘要:迭代器模式的需求来自:需要对一些集合进行迭代,而迭代的方式可能有很多种。 说到迭代,动作大致包括设置第一个位置,获取下一个位置元素,判断是否迭代结束,获取当前位置元素,大致就这么些。把这些迭代动作封装到一个接口中。 public interface IIterator { void First(); string Next(); bool I...
阅读全文
摘要:假设有一个软件公司,每当有新产品推出,就把信息通知到一些客户。 把通知这个动作抽象成一个接口。 public interface IService { void Notif(); }客户如果想获得通知,就需要实现以上的接口。这里的客户被看作是观察者。 public class CustomerA : IService { p...
阅读全文
摘要:当从应用程序全局的角度来看,如果只允许类的一个实例产生,就可以考虑单例模式。 □ 即时加载的单例模式 把类的实例赋值给类的一个静态字段。 class Program { static void Main(string[] args) { Logger log = Logger.GetInstance(); log....
阅读全文
摘要:所谓的"对象为Null模式",就是要求开发者考虑对象为Null的情况,并设计出在这种情况下的应对方法。 拿"用最简单的例子理解策略模式(Strategy Pattern) "中的例子来说,在我们的客户端程序中只考虑了用户输入1,2,3的情况,如果用户输入其它数字,比如4,就没有一个对应的IBall接口实现类实例产生,于是会报如下的错: 为了应对这种情况,我们专门设计一个类,当用户输入1,2,3...
阅读全文
摘要:当一个动作有多种实现方法,在实际使用时,需要根据不同情况选择某个方法执行动作,就可以考虑使用策略模式。 把动作抽象成接口,比如把玩球抽象成接口。 public interface IBall { void Play(); }有可能是玩足球、篮球、排球等,把这些球类抽象成实现接口的类。 public class Football : IBall { ...
阅读全文
摘要:"延迟加载"是指在需要的时候再加载数据。比如获得一个Customer信息,并不会把该Customer的Orders信息一下加载出来,当需要显示Orders的时候再加载。简单来说,就是按需加载。使用"延迟加载"的好处是减少应用程序响应时间,降低内存消耗,避免不必要的数据库交互。 □ 即时加载 创建Order类和Customer类,Customer中维护着Order的一个集合,在Customer的构...
阅读全文
摘要:当谈到垃圾回收,在C#中,托管资源的垃圾回收是通过CLR的Garbage Collection来实现的,Garbage Collection会调用堆栈上对象的析构函数完成对象的释放工作;而对于一些非托管资源,比如数据库链接对象等,需要实现IDisposable接口进行手动的垃圾回收。那么什么时候使用Idisposable接口,以及如何使用呢? public interface IDisposabl...
阅读全文