程杰
着重从c#代码角度分析学习心得: 学设计模式,不需要是否能立刻理解和记忆,无需着力
首先是UML图 再从设计模式到UML图从UML图到代码其次知道各种模式的应用场景即可第三寻找到各种模式的经典应用实例设计模式心得
第29章 OOTV杯超级模式大赛–模式总结
作者谈了自己对design patterns学习理解,可供参考
Ref GoFjava与模式,阎宏为了简化程序,计算器程序采用 c# 多个button 对应同一消息处理方法
//各个button共用同一个事件处理函数button1.click = new System.EventHandler(button_Click); button2.click = new System.EventHandler(button_Click); button3.click = new System.EventHandler(button_Click); ...private void button_Click(objet sender ,EventArgs e){ Button btn =(Button)sender ; //实例化按钮,从而获取当前单击按钮的值 this.txtvalue.Text = btn.Text; //窗体中有txtvalue控件并给它赋值}factory
类:abstract product
: concrete product
对比UML图,理解代码;或反之
工厂模式: 实例化具有共同父类的不同对象 应用: EJB,RMI,CORBA可根据不同条件产生不同实例switch-case
或 反射要素 工厂: 虚拟构造器分类 简单工厂模式工厂方法模式抽象工厂模式简单工厂模式的结构
工厂方法模式
深入浅出UML类图: 有价值,理解UML作用Strategy
类和Context
类为aggregate关系,即Strategy
将作为构造函数的参数传递给`Context
类//抽象算法类abstract class Strategy{ //算法方法 public abstract void algorithmInterface();}//上下文class Context{ Strategy strategy; public Context(Strategy strategyIn) {} }Context
类控制 -> switch-case
选择,即具体策略的选择也交予Context
类处理
策略模式Context
switch-case
依然去不掉。原因在哪里?Assembly.Load("程序集名称").CreateInstance("名称空间.类名称")
?
单一职责原则(SRP:Single responsibility principle)
案例
六大原则之SRP笔记子类型可替换性
有点像pipeline?
GOF: 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。Component
classabstract class Component{ public abstract void Operation();}ConcreteComponent
classclass ConcreteComponent : Component{ public override void Operation(){ Console.WriteLine("具体对象操作"); }}Decorator
classabstract class Decorator : Component{ protected Component component; public void setComponent(Component component) { this.component = component; //设置Component } // public override void Operation(){ if(component != NULL){ component.Operation();} }}ConcreteDecoratorA
classclass ConcreteDecoratorA : Decorator { private string addState; public override void Operation(){ base.Operation(); ... } }ConcreteDecoratorB
class
Client
code
我认为客户端代码就是 pipeline
Example: 加密数据和过滤词汇是数据处理模块的装饰功能,若先加密再过滤,则不妥!
装饰模式 vs. 桥接模式 ??vs. 责任链模式 责任链: 表示上下级审批权限装饰: pipeline实际应用:Java IO
流是典型的装饰模式结构图
结构图
代理模式原理及实例讲解
代理模式角色分为 4 种:
主题接口:定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法;真实主题:真正实现业务逻辑的类;代理类:用来代理和封装真实主题;Main:客户端,使用代理类和主题接口完成一些工作。Subject
类: 定义RealSubject
和Proxy
的公用接口abstract class Subject{ public abstract void Request();}RealSubject
类: 定义Proxy
所代表的真正实体class RealSubject : Subject{ public override void Request(){}}Proxy
类:class Proxy : Subject{ RealSubject real; public override void Request(){ if(real == NULL) real = new RealSubject(); }}客户端代码static void Main(string[] args){ Proxy proxy = new Proxy(); //代理 proxy.Request();}客户端
Operation oper;oper = OperarionFactory.createOperate("+");oper.NumberA=1;oper.NumberB=2;double result = oper.GetResult();工厂接口
interface IFactory{ Operator CreateOperation();}具体工厂类
//加法工厂Class AddFactory : IFactory{ public Operation CreateOperation{ return new OperationAdd(); }}...//除法工厂Class DivFactory : IFactory{ public Operation CreateOperation{ return new OperationDiv(); }}客户端
IFactory operFactory = new AddFactory();Operation oper = operFactory.CreateOperation();Operation oper;oper = OperarionFactory.createOperate("+");oper.NumberA=1;oper.NumberB=2;double result = oper.GetResult();原型类
abstract class Prototype{ private string id; public Prototype(string id) {this.id = id;} public string Id { get {return id;} } //抽象类的关键 public abstract Prototype Clone();}`具体原型类
class ConcretePrototype : Prototype{ pulic ConcretePrototype(string id) : base(id) {} public override Prototype Clone(){ //创建当前对象的浅表副本 return (Prototype) this.MemberwiseClone(); }}客户端
MemberWiseClone
: 浅clone方法,通过创建一个新对象,并把所有当前对象中非静态域复制到新对象中,从而创建一个浅拷贝。对于值类型的域,进行的是按位拷贝。对于引用类型的域,引用会被赋值而引用的对象则不会。因此,原始对象及其克隆都会引用同一个对象。注意,这种方法对派生类都是有效的,也就是说,你只需在基类中定义一次Clone方法。static void Main(string[] args){ ConcretePrototype p1 = new ConcretePrototype("I"); ConcretePrototype c1.p1.Clone(); ...}Clone 分浅拷贝和深拷贝
两者区别:当有引用类型成员时,浅拷贝复制的是成员的引用,深拷贝复制的是成员对象。ICloneable接口
简历类
class Resume : ICloneable{ public Object Clone(){ return (Object) this.MemberwiseClone(); }} -
MemberwiseClone
: 复制时,对于类中的值类型会创建新的变量,而对于引用变量来说,会指向原来的引用并不创建新的引用变量
简历类
class Resume : IClonealbe{ ... private Resume(WorkExprience work){ this.work = (WorkExprience) work.Clone(); } ... public Object Clone(){ Resume obj = new Resume(this.work); }}virtual
抽象类AbstractClass
abstract class AbstractClass{ public abstract void PrimitiveOperation1(); public abstract void PrimitiveOperation2(); public void templateMethod(){ PrimitiveOperation1(); PrimitiveOperation1(); Console.WriteLine(""); }}ConcreteClass
class ConcreteClassA : AbstractClass{ public override void PrimitiveOperation1(){ Console.WriteLine("具体A类方法 1 实现"); } public abstract void PrimitiveOperation2(){ Console.WriteLine("具体A类方法 2 实现"); }}迪米特法则(Law of Demeter): 又叫作最少知识原则(Least Knowledge Principle, LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。英文简写为: LoD. talk only to your immediate friends
设计模式的门面模式(Facade)和中介模式(Mediator),都是迪米特法则应用的例子
Facade相当于增加一个接口层,向client提供简洁API接口,同时屏蔽低层复杂的遗留代码
example
建筑流程是确定,往往建筑一座楼房包括下面步骤:(1)打桩,建立基础(2)建立框架等。建造者模式的本质和建造楼房是一致的:即流程不变,但每个流程实现的具体细节则是经常变化。建造者模式的好处就是保证流程不会变化,流程即不会增加、也不会遗漏或者产生流程次序错误,这是非常重要的。 check list 实现么?Product: 产品类,由多个部件组成
class Product { IList<string> parts = new IList<string>(); //添加产品部件 public void Add(string part) { parts.Add(part); }}Builder: 抽象建造者类,确定产品组成: PartA与PartB,并返回结果。
abstract class Builder{ public abstract void BuilderPartA(); public abstract void BuilderPartB(); public abstract Product GetResult();}注意: Builder只生产,不规定流程次序;而Dirctor强调规定流程次序ConcreteBuilder: 注意: ConcreteBuilder与Product为关联关系
class ConcreteBuilder1 : Builder { private Product product = new Product(); public override void BuildPartA() {} ... }Director: 指挥者类,规定流程次序!
class Director{ public void Construct(Builder builder) { //生产次序,important builder.BuildPartA(); builder.BuildPartB(); }}客户端
static void Main(string[] args){ Director director = new Director(); Builder b1 = new ConcreteBuilder1(); director.Constructor(b1); Product p1 = b1.GetResult(); ...}前台秘书类
class Secretary{ //同事列表 private IList<Investor> investors = new List<Investor>; //添加成员 public void Attach(Investor invest) { investors.Add(invest); } //发送通知 public void Notify() { foreach( Investor i in investors ) i.Update(); } //前台状态 public string SecretaryAction { get { return action; } set { action = value; } }}看股票同事类
class Investor { private string name; private Secretary sub; public Investor(string name, Secretary sub){...} public Update() {}}客户端代码
static void Main(string[] args){ Secretary mm = new Secretary(); //前台小姐mm //看股票的同事 Investor one = new Investor("One",mm); Investor two = new Investor("Two",mm); //前台记录下两个待通知的同事 mm.Attach(one); mm.Attach(two); mm.Notify(); //通知同事}结构图
观察者模式: 又称发布/订阅(Publish/Subscribe)模式
Subject
类: 抽象通知者
Observer
类: 抽象观察者abstract class Observer{ public abstract void Update();}ConcreteSubject
类: 具体通知者class ConcreteSubject : Subject { private string subjectState; //状态 public string SubjectState { get { return subjectState; } set { subjectState = value; } }}ConcreteObserver
类: 具体观察者客户端代码SQL
class SqlserverUser{ public void insert(User user) { Console.WriteLine("SQL Server insert a record"); }}IUser 接口
interface IUser{ void Insert(User user); User GetUser(int id);}SqlserverUser类:访问SQL Server的User
class SqlserverUser : IUser{ public void Insert(User user){ Console.WriteLine("insert a record into SQL Server Database"); } public User GetUser(int id){ Console.WriteLine("get User's a record from SQL Server according to ID"); return null; }}accessUser类: 用于访问Acess的User
class AccessUser : IUser{ public void Insert(User user){ Console.WriteLine("insert a record into Access Database"); } public User GetUser(int id){ Console.WriteLine("get User's a record from Access according to ID"); return null; }}IFactory接口: 定义访问User的抽象工厂接口
interface IFactory{ IUser CreateUser();}SqlServerFactory类: 实现IFactory接口
class SqlServerFactory{ public IUser CreateUser(){ return new SqlserverUser(); }}AccessFactory类: 实现IFactory接口
class AccessFactory{ public IUser CreateUser(){ return new AccessUser(); }}客户端
static void Main(string args){ User user = new User(); IFactory factory = new SqlServerFactory(); IUser iu = factory.CreateUser(); iu.Insert(user); iu.GetUser(1); Console.Read();}增加了部门表Department
的处理
SqlserverDepartment类: 用于访问SQL Server的Department
class SqlserverDepartment : IDepartment{ ...}修改IFactory类,增加了访问Department表的抽象工厂接口
interface IFactory{ IUser CreateUser(); IDepartment CreateDepartment(); //增加新接口}SqlServerFactory类: 实现IFactory接口
class SqlServerFactory : IFactory{ public IUser CreateUser(){ return new SqlserverUser(); } public IDepartment CreateDepartment() { return new SqlserverDepartment(); }}客户端
static void Main(string[] args){ User user = new User(); Department dept = new Department(); //AbstractFactory factory = new SqlServerFactory(); IFactory factory = new AccessFactory(); IUser iu = factory.CreateUser(); iu.Insert(user); iu.GetUser(1); IDepartment id = factory.CreateDepartment(); id.Insert(dept); id.GetDepartment(1); Console.Read();}客户端
static void Main(string[] args){ User user = new User(); Department dept = new Department(); IUser iu = DataAccess.CreateUser(); iu.Insert(user); iu.GetUser(1); IDepartment id = DataAccess.CreateDepartment(); id.Insert(dept); id.GetDepartment(1); Console.Read();}Assembly.Load(AssemblyName).CreateInstance(className);
using System.Reflection;class DataAccess{ private static readonly string AssemblyName = "抽象工厂模式"; private static readonly string db = "Sqlserver"; //private static readonly string db = "Access"; public static IUser CreateUser() { string className = AssemblyName + "." + db + "User"; return (IUser)Assembly.Load(AssemblyName).CreateInstance(className); } public static IDepartment CreateDepartment() { string className = AssemblyName + "." + db + "Department"; return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className); }}new issue: 更换数据库访问时,还需改变db
app.config
通过配置文件来解决<?xml version="1.0" encoding="utf-8" ?><configuration> <appSettings> <add key="DB" value="Sqlserver"/> </appSettings></configuration>C#读取配置文件
private static readonly string db = ConfigurationManager.AppSettings["DB"];app.config
State类: 抽象状态类
abstract class State { public abstract void Handle(Context context);}ConcreteState类: 具体状态,每一子类实现与一个Context的状态相关行为
class ConcreteStateA : State { public override void Handle(Context context) { //下一状态为ConcretexStateB //自动机状态 -> 变迁 context.State = new ConcretexStateB(); }}class ConcreteStateB : State { public override void Handle(Context context) { //下一状态为ConcretexStateA //自动机状态 -> 变迁 context.State = new ConcretexStateA(); }}Context类: 维护一个ConcreteState子类的实例,该实例定义当前状态
class Context { private State state; public Context(State state) {this.state = state;} public State State { get {return state;} set { state = value; ... } } public void Request() {state.Handle(this);}}Target: 客户端适配接口
class Target { public virtual void Request() {}}Adaptee: 待适配类
class Adaptee { public virtual void SpecificRequest() {}}Adapter: 实际适配类,内部包装一个Adaptee对象,实现接口转换
class Adapter : Target { //包装 private Adaptee adaptee = new Adaptee(); public virtual void Request() { adaptee.SpecificRequest(); //转换 }}客户端代码
static void Main(string[] args){ Target target = new Adapter(); target.Request();}我认为本节示例有不合理成分,比如外籍中锋为中锋的子类,又比如有外籍后卫呢?
我认为应该改为下图所示: 即 + 组合模式(第19章)
发起者(Originator)
class Originator { private string state; public string State { get {return state;} set {state = value;} } public Memento CreateMemeto() { return Memetor(state); } public void SetMemento(Memento memento){ state = memento.State; } public void Show(){ Console.WriteLine("State=" + state); }}备忘录(Memento)类
class Memento { private string state; public Memento(string state) {this.state = state;} public string State { get {return state;} }}管理者(Caretaker):
class Caretaker { private Memento memento; public Memento Memento { get {return memento;} set {memento = value;} }}博文写得很好,还有时序图,比书上介绍的更清楚! 本书作者 程杰 示意图 没有引入 Client行为时序图,很难表现 Design pattern使用方式!
Component: 组合中对象声明接口
abstract class Component { protected string name; public Component(string name) {this.name = name;} public abstract void Add(Component c); public abstract void Remove(Component c); public abstract void Display(Component c);}Leaf: 表示组合中叶节点 -> 无子节点
class Leaf : Component { pulic Leaf(string name) : base(name) {} ...}Composite: 表示枝节点,有子节点
class Composite : Component { //保存下属的枝/叶节点 private List<Component> children = new List<Component>();}Iterator -> 遍历
Iterator迭代器抽象类
abstract class Iterator { public abstract object First(); public abstract object Next(); public abstract bool IsDone(); public abstract object CurrentItem();}Aggregate聚焦抽象类
abstract class aggregate { public abstract Iterator createIterator(); //创建迭代器}ConcreteIterator: 具体迭代器类
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 bool IsDone(){ return current >= aggregate.Count? true : false; } public override object CurrentItem(){ return aggregate[current]; }}ConcreteAggregate: 具体聚集类
class Concreteaggregate : Aggregate { private IList<object> items = new List<Object>(); public override Iterator(this){ return Concreteaggregate(this); } public int Count { //聚焦总数 get {return items.Count;} } public object this[int index] { get {return items[index];} set {items.Insert(index,value);} }}客户端代码
foreach
必须要实现IEnumerable
和IEnumerator
接口IEumerator
: 支持对非泛型集合的简单迭代
IEnumerable
: 该枚举数支持在非泛型集合上进行简单的迭代
foreach in
实际通过IEnumerable
和IEumerator
接口实现的GetInstance()
public partial class FormToolBox : Form{ private static FormToolBox ftb = null;//Static var //构造函数私有化,外部代码不能直接new来实例化 private FormToolBox(){ InitializeComponent(); } public static FormToolBox GetInstance(){ if(ftb == null | ftb.IsDisposed){ ftb = new FormToolBox(); ftb.MdiParent = Form. } }}form==null
: 是把该窗体对象设置为空,但该form仍存在内存里Singleton类
class Singleton{ private static Singleton inst; private Singleton(){} public static Singleton GetInstance() { if(inst == null) inst = new Singleton(); return inst; }}客户端代码
static Main(string[] args){ Singleton s1 = Singleton.GetInstance(); Singleton s2 = Singleton.GetInstance(); if(s1 == s2) Console.WriteLine("s1's address is as same as s2"); Console.Read();}lock()
sealed
?readonly
?DP: 尽量用合成/聚合,尽量不用类继承
CompositionAggregation手机软件抽象类
abstract class HandSoft { public abstract void Run();}游戏、通讯录具体类
class HandsetGame : HandsetSoft {}class HandsetAddrList : HandsetSoft {}手机品牌类
abstract class HandsetBrand { protected HandsetSoft soft; //设置手机软件 public void SetHandsetSoft(HandsetSoft soft) {this.soft = soft;}}手机品牌具体类
- 按照软件分类实现结构图
- 桥接
Implementor类
abstract class Implementor { public abstract void Operation();`}派生类
class ConcreteImplementorA : Implementor { ... }Abstraction类
class Abstraction { protected Implementor imp;}RefinedAbstract类
客户端
对比组合模式(第19章)关联
抽象命令类
public abstract class Command{ protected Barbecuer receiver; public Command(Barbecuer recv){ receiver = recv; } //执行命令 abstract public void ExecuteCom();}具体命令类
//烤羊肉串public class BakeMuttonCom : Command{ public BakeMuttonCom(Barbecuer recv) : base(recv) { receiver = recv; } public override void ExecuteCom() { receiver.BakeMutton(); //具体执行行为 }}//烤鸡翅命令public class BakeChickenCom : Command{ public BakeChickenCom(Barbecuer recv) : base(recv) { receiver = recv; } public override void ExecuteCom() { receiver.BakeChicken(); //具体执行行为 }}服务员类
public class Waiter{ private Command com; //设置订单 public void SetOrder(Command com) {this.com = com;} //通知执行 public void Notify(){ com.ExecuteCom(); }}客户端
Command: 执行操作的接口
abstract class Command{ protected Receiver receiver; public Command(Receiver recv) {receiver = recv;} abstract public void Execute();}ConcreteCommand:
class ConcreteCommand : Command{ public ConcreteCommand(Receiver recv) : base(recv){} public void Execute() {receiver.Action();}}Invoker:
class Invoker{ private Command command; public void SetCommand(Command com) {command = com;} public void ExecuteCommand(){ command.Execute(); }}Receiver:
class Receiver{ public void Action() {}}客户端
static void Main(string[] args){ Receiver r = new Receiver(); Command c = new Command(r); //r为关联类 Invoker i = new Invoker(); i.SetCommand(); i.ExecuteCommand();}Handler类:定义一个处理请求的接口
abstract class Handler { protected Handler successor; //设定继任者 public void SetSuccessor(Handler suc) {this.successor = suc;}}ConcreteHandler1: 当请求数在0-10之间有权处理,否则转到下一层级处理
class ConcreteHandler1 : Handler{ public override void HandleRequest(int req) { if(req >= 0 && req < 10) { ... }else if(successor != NULL) { successor.HandleRequest(req); } }}ConcreteHandler2: 当请求数在10-20之间有权处理,否则转到下一层级处理
class ConcreteHandler2 : Handler{ public override void HandleRequest(int req) { if(req >= 10 && req < 20) { ... }else if(successor != NULL) { successor.HandleRequest(req); } }}ConcreteHandler3: 当请求数在20-30之间有权处理,否则转到下一层级处理
class ConcreteHandler3 : Handler{ public override void HandleRequest(int req) { if(req >= 20 && req < 30) { ... }else if(successor != NULL) { successor.HandleRequest(req); } }}客户端
static void Main(string[] args){ Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); Handler h3 = new ConcreteHandler3(); //设置责任链上/下家 h1.SetSuccessor(h2); h2.SetSuccessor(h3); int[] reqs = [2,5,14,22]; foreach(int req in reqs) {h1.HandleRequest(req);}}Mediator:
abstract class Mediator { public abstract void Send(string msg, Colleague colleague);}Colleague:
abstract class Colleague { protected Mediator mediator; //获取中介者对象 public Colleague(Mediator mediator) {this.mediator = mediator;} }ConcreteMediator:
class ConcreteMediator : Mediator { private ConcreteColleague1 c1; private ConcreteColleague2 c2;}?
Flyweight: 享元类的接口和抽象类
abstract class Flyweight{ public abstract void Operate(int extraState);}ConcreteFlyweight:
abstract class ConcreteFlyweight : Flyweight{ public override void Operate(int extraState) {}}UnsharedConcreteFlyweight:
abstract class UnsharedConcreteFlyweight : Flyweight{ public override void Operate(int extraState) {}}FlyweightFactory: 享元工厂
class FlyweightFactory{ private Hashtable flyweights = new Hashtable(); public FlyweightFactory(){ flyweights.Add("X", new ConcreteFlyweight()); flyweights.Add("Y", new ConcreteFlyweight()); flyweights.Add("Z", new ConcreteFlyweight()); } public Flyweight GetFlyweight(string key){ //根据客户要求,返回已生成的实例 return ((Flyweight) flyweights[key]); }}客户端
static void Main(string[] args){ int etraState = 22; FlyweightFactory f = new FlyweightFactory(); Flyweight fx = f.GetFlyweight("X"); ...}个人觉得: 作者没有指出享元模式的核心设计思想?
享元模式核心: 池化机制 = 资源调度 + 分配 + 回收
对象池,如线程池、数据库连接池等服务器资源池化技术思想: 将设备资源都被放到一个池内,再进行统一分配。
例如CPU 池、内存池、存储池资源的池化使得用户不再关心计算资源的物理位置和存在形式,IT部门也得以更加灵活地对资源进行配置。AbstractExpression: 抽象表达式,该接口为抽象语法树中所有节点共享
abstract class AbstractExpression { public abstract void Interpret(Context context);}TerminalExpression: 终结符表达式
class TerminalExpression : AbstractExpression { public override void Interpret(Context context) {...}}NoterminalExpression: 非终结符表达式
class NonterminalExpression : AbstractExpression { public override void Interpret(Context context) {...}}Context: 上下文
class Context{ private string input; public string Input { get {return input;} set {input = value;} } ...}客户端:
static void Main(string[] args){ Context context = new Context(); IList<AbstractExpression> list = new List<AbstractExpression>(); list.Add(new TerminalExpression()); ... foreach(AbstractExpression exp in list) {exp.Interpret(context);} }演奏内容类 context:
class PlayContent{ //演奏文本 private string text; public string PlayText { get {return text;} set {text=value;} }}表达式类 AbstractExpression:
abstract class Expression{ //解释器 public void Interpret(PlayContent content) { ... } //执行 public abstract void Excute(string key, double value);}音符类 TerminalExpression:
class Note : Expression { public override void Excute(string key, double value) {...}}音阶类 TerminalExpression:
class Scale : Expression { public override void Excute(string key, double value) {...}}客户端
switch
-> 简单工厂 + 反射?抽象类
abstract class Action{ //得到男人结论或反应 public abstract void GetManConclusion(Man concreteElementA); //得到女人结论或反应 public abstract void GetWomanConclusion(Man concreteElementB);}//人abstract class Person{}具体类
//男人 class Man : Person { public override void Accept(Action visitor) { visitor.GetManConclusion(this); } } //女人 class Woman : Person { public override void Accept(Action visitor) { visitor.GetWomanConclusion(this); } }双分派//对象结构class ObjectStructure{ private IList<Person> elements = new List<Person>(); //增加 public void Attach(Person element) { elements.Add(element); } //移除 public void Detach(Person element) { elements.Remove(element); } //遍历查看显示 public void Display(Action visitor) { foreach (Person e in elements){ e.Accept(visitor); } }}客户端
static void Main(string[] args){ ObjectStructure o = new ObjectStructure(); o.Attach(new Man()); o.Attach(new Woman()); Success v1 = new Success(); o.Display(v1); //遍历Man和Woman的不同反应 Failing v2 = new Failing(); o.Display(v2); Amativeness v3 = new Amativeness(); o.Display(v3); Marriage v4 = new Marriage(); o.Display(v4); Console.Read();}visitor类
abstract class Visitor{ public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA); public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);}具体访问类
class ConcreteVisitor1 : Visitor{ public override void VisitConcreteElementA(ConcreteElementA concreteElementA) { Console.WriteLine("{0}被{1}访问", concreteElementA.GetType().Name, this.GetType().Name); } public override void VisitConcreteElementB(ConcreteElementB concreteElementB) { Console.WriteLine("{0}被{1}访问", concreteElementB.GetType().Name, this.GetType().Name); }}Element类: 定义一个accept操作,以访问者为参数
abstract class Element{ public abstract void Accept(Visitor visitor);}ConcreteElementA
class ConcreteElementA : Element{ public override void Accept(Visitor visitor) { visitor.VisitConcreteElementA(this); } public void OperationA() { }}objectStructure类: 遍历
class ObjectStructure{ private IList<Element> elements = new List<Element>(); public void Attach(Element element) { elements.Add(element); } public void Detach(Element element) { elements.Remove(element); } public void Accept(Visitor visitor) { foreach (Element e in elements) { e.Accept(visitor); } }}get
set
base
? - delegate - event
附 录 B 参考文献
新闻热点
疑难解答