一.备忘录模式
1.概念
备忘录(Memento),即在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到先前保存的状态.
2.应用
备忘录其实就是对象的存档.首先需要区分对象中哪些状态(字段或属性)的值需要保存,将这些状态抽象为一个新的备忘录(Memento)类,用这个类对象保存这些状态值,可以提供一个备忘录对象的管理类,将所有备忘录对象使用键值对等方式存储起来.必要时找到相应的备忘录,然后就可以还原对象某个时刻的状态.
二.组合模式
1.概念
组合模式(Composite),是一种结构型模式,将对象组合成属性结构表示"部分-整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性.
2.应用
组合模式的应用可以理解为就是树的应用.定义一个公共的接口,这个接口可以有两种实现类,一种是非叶子节点,在实现方法中调用子节点的相应方法;一种是叶子节点,在实现方法中实际完成相应的功能.组合模式适用于对一些树形结构的功能抽象.
三.迭代器模式
1.概念
迭代器模式(Iterator),提供了一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示.
2.应用
迭代器应该是很常用的,在C#中的foreach循环就是使用了迭代器.迭代器模式是针对容器的遍历的,我们只需要提供一个Iterator接口,其中定义了Next()等方法,然后在定义好的遍历方法中调用迭代器接口中的方法.对于自定义的容器,要想能够被foreach遍历,只需要实现迭代器接口实现这些方法即可.在C#中,ListDictionary等数据容器都实现了迭代器接口.
四.桥接模式
1.概念
桥接模式(Bridge),其将抽象部分与它的实现部分分离,使它们都可以独立地变化.
2.示例类图
3.示例代码:
using System; using System.Collections.Generic; using System.Text; namespace DesignPatternsCore { /// <summary> /// 抽象维度父类 /// </summary> public class Abstraction { public Implementor imp; public virtual void Operation() { imp.OperationImp(); } } /// <summary> /// 提炼出来的抽象维度类 /// </summary> public class RefinedAbstraction : Abstraction { public override void Operation() { base.Operation(); } } /// <summary> /// 实现维度接口 /// </summary> public interface Implementor { void OperationImp(); } /// <summary> /// 具体的实现维度 /// </summary> public class ImplementorA : Implementor { public void OperationImp() { Console.WriteLine("implementor a operate"); } } }
4.总结:
桥接模式将实现和抽象做了分离.我们可以理解为实际的系统中可能从多个角度进行分类,每一种分类都可能变化,那么桥接模式能分离这些不同的角度,让它们独立变化,减少耦合.
五.命令模式
1.概念:
命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作.
2.示例类图:
3.示例代码:
using System; using System.Collections.Generic; using System.Text; namespace DesignPatternsCore { /// <summary> /// 发起命令的类 /// </summary> public class Invoker { //可以使用字典存储所有的命令 private Dictionary<string, Command> allCommandsDic; public Invoker() { allCommandsDic = new Dictionary<string, Command>(); } //注册命令 public void RegistCommand(string commandName,Command command) { if (!allCommandsDic.ContainsKey(commandName)) { allCommandsDic.Add(commandName, command); } else { Console.WriteLine("commandName repeated"); } } //移除命令 public void RemoveCommand(string commandName) { if (allCommandsDic.ContainsKey(commandName)) { allCommandsDic.Remove(commandName); } } //执行命令 public void ExecuteCommand(string commandName) { if (allCommandsDic.ContainsKey(commandName)) { allCommandsDic[commandName].Execute(); } } } /// <summary> /// 命令父类 /// </summary> public class Command { protected Receiver receiver; public Command(Receiver receiver) { this.receiver = receiver; } public virtual void Execute() { } } /// <summary> /// 命令A /// </summary> public class CommandA : Command { public CommandA(Receiver receiver) : base(receiver) { } public override void Execute() { //调用接收者的相应方法 receiver.ActionA(); } } /// <summary> /// 命令B /// </summary> public class CommandB : Command { public CommandB(Receiver receiver) : base(receiver) { } public override void Execute() { //调用接收者的相应方法 receiver.ActionB(); } } /// <summary> /// 具体的执行者 /// </summary> public class Receiver { public void ActionA() { Console.WriteLine("action a"); } public void ActionB() { Console.WriteLine("action b"); } } }
4.总结:
命令模式的重点在于使接收请求的一方和处理请求的一方解耦,相互之间不可知.具体的命令可以看作是请求的转交者,在转交请求时有时需要对传入的数据一并进行处理,这有一点MVC的味道.
命令模式和观察者模式有一定的相似之处.命令模式的各种命令也可以使用多种方式存储(键值对或委托),命令不一定是一个类对象,也可以只是一个方法.命令模式重点在于对请求的转交,一条命令一般触发一个命令(也可以使用复合命令组合各种基本命令,可以视作执行了多个命令),观察者模式则是对象自身存储被观察者的引用,在自身发生特定改变后通知所有被观察者(调用被观察者的相应方法).
六.职责链模式
1.概念:
职责链模式(Chain of Responsibility),使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止.
2.示例类图:
3.示例代码:
using System; using System.Collections.Generic; using System.Text; namespace DesignPatternsCore { /// <summary> /// 职责链 /// </summary> public class ChainOfResponsibility { //可以使用多种方式存储请求的处理者,使用数组List键值对或链式存储(保存下一个处理者对象的引用)等方式都可以 //这里使用List private List<IHandler> allHandlerList; public ChainOfResponsibility() { allHandlerList = new List<IHandler>(); } /// <summary> /// 添加处理者 /// </summary> /// <param name="handler"></param> public void AddHandler(IHandler handler) { allHandlerList.Add(handler); } /// <summary> /// 移除处理者 /// </summary> /// <param name="handler"></param> public void RemoveHandler(IHandler handler) { for (int i = 0; i < allHandlerList.Count; i++) { if(allHandlerList[i] == handler) { allHandlerList.RemoveAt(i); return; } } } /// <summary> /// 处理请求 /// </summary> /// <param name="requestParam"></param> /// <returns>请求是否得到处理</returns> public bool HandleRequest(int requestParam) { //遍历所有处理者,如果有一个处理者处理了请求,立即返回 for(int i = 0;i < allHandlerList.Count; i++) { if (allHandlerList[i].HandleRequest(requestParam)) { return true; ; } } return false; } } /// <summary> /// 请求处理者接口 /// </summary> public interface IHandler { /// <summary> /// 处理实际请求的方法 /// </summary> /// <param name="requestParam"></param> /// <returns>是否处理了此请求</returns> bool HandleRequest(int requestParam); } /// <summary> /// 实际请求处理者A /// </summary> public class HandlerA : IHandler { public bool HandleRequest(int requestParam) { if(requestParam > 10) { Console.WriteLine("handler a handle request"); return true; } else { return false; } } } /// <summary> /// 实际请求处理者B /// </summary> public class HandlerB : IHandler { public bool HandleRequest(int requestParam) { if (requestParam > 0 && requestParam <= 10) { Console.WriteLine("handler b handle request"); return true; } else { return false; } } } /// <summary> /// 实际请求处理者C /// </summary> public class HandlerC : IHandler { public bool HandleRequest(int requestParam) { if (requestParam <= 0) { Console.WriteLine("handler c handle request"); return true; } else { return false; } } } }
4.总结
职责链模式中,对于多个请求的处理者,可以使用一个合适的数据结构进行存储,如链式存储(链表)或线性存储(数组等).虽然这个模式名称是职责链,但是不是说所有请求的处理者一定要使用链式存储.在调用的过程中,遍历存储的所有处理者,如果有一个处理者成功处理了请求,就不再向下遍历.
在通信的过程中,对于接收到的消息可以统一处理,也可以在不同的模块中分散处理(各自处理自己的消息).如果使用分散处理消息的方式就可以使用职责链模式.
七.享元模式
1.概念:
享元模式(Flyweight),即运用共享技术有效地支持大量细粒度的对象.
2.应用:
对一个程序而言,可以将所有对象粗略分为外部状态和内部状态两类,如数据模块一般都是内部状态.享元模式就是共享元素或者说内部状态的共享,如数据的共享等.享元模式的一个重要应用就是各种池,如线程池对象池等.