目录
一、访问者模式
访问者模式表示一个作用于某对象结构中的各元素操作。它使你在不改变各元素的类的前提下定义作用于这些元素的操作。
它增加状态比较简单,符合开闭原则,但是增加元素困难,不符合开闭原则。类似于抽象工厂,以一种倾斜的方式扩展(方法集合的可扩展和类集合的不可扩展)。
本质是预留通路,回调实现。
当操作需要更改时,将更新封装到一个类中,并由等待更改类提供一个接口。
需要注意:
1、访问者模式适用于数据结构稳定,而操作可以不稳定。将操作和数据结构解耦。
2、数据结构每一个节点都可以接受一个访问的调用,这个节点将自己传入访问者,访问者执行节点对象的操作--双重分派。
3、操作基于数据结构和访问者的数据类型。
4、有一个非常重要的结构类,结构对象会保存一系列节点类,下文中 节点类调用自己的ACCEPT函数,将VISITOR传入,然后VISITOR对象执行操作。
pros and cons
pros:
1、增加新的操作非常容易,即增加一个访问者类
2、将有关行为集中到一个访问者对象中,而不是节点中。
cons:
1、增加新的节点十分困难。若增加新节点,就要在抽象访问者中增加一个新操作。不符合开闭原则。
2、破坏了封装,访问者对象要访问并调用节点对象的操作。节点类必须暴露自己的一些操作和内部状态。
二、访问者模式角色
1、抽象元素类
元素类结构稳定,就像下面的例子,人有男女之分,结构稳定。
2、具体元素类,就像男人女人类。
3、抽象访问者类
有抽象函数,并且参数是抽象元素类,便于回调。
4、具体类
实现抽象状态类中抽象方法。
5、结构类
集中处理,迭代遍历。
三、代码实例一
访问者类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
abstract class Action
{
public abstract void ManAction( Man man);
public abstract void WomanAction(Woman woman);
}
}
具体访问者类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
class Love : Action
{
public override void ManAction(Man man)
{
Console.WriteLine(man.GetType().Name + " 恋爱 " + this.GetType().Name);
}
public override void WomanAction(Woman woman)
{
Console.WriteLine(woman.GetType().Name + " 恋爱 " + this.GetType().Name);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
class Fail : Action
{
public override void ManAction(Man man)
{
Console.WriteLine(man.GetType().Name + " 失败 " + this.GetType().Name);
}
public override void WomanAction(Woman woman)
{
Console.WriteLine(woman.GetType().Name + " 失败 " + this.GetType().Name);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
class Success : Action
{
public override void ManAction(Man man)
{
Console.WriteLine(man.GetType().Name + " 成功 " + this.GetType().Name);
}
public override void WomanAction(Woman woman)
{
Console.WriteLine(woman.GetType().Name + " 成功 " + this.GetType().Name);
}
}
}
元素类,有一个Accept函数,参数为状态类型。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
abstract class Person
{
public abstract void Accept(Action visitor);
}
}
一般元素类的子类是固定的。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
class Man : Person
{
public override void Accept(Action visitor)
{
visitor.ManAction(this);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
class Woman : Person
{
public override void Accept(Action visitor)
{
visitor.WomanAction(this);
}
}
}
结构类,便于批处理
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
class Structure
{
private List<Person> lists = new List<Person>();
public void Attach(Person person)
{
lists.Add(person);
}
public void Detach(Person person)
{
lists.Remove(person);
}
public void Run(Action visitor)
{
foreach (Person person in lists)
{
person.Accept(visitor);
}
}
}
}
测试
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace VisitorOne
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Structure structure = new Structure();
structure.Attach(new Man());
structure.Attach(new Woman());
Success success = new Success();
structure.Run(success);
structure.Run(new Love());
structure.Run(new Fail());
}
}
}
如果想再增加一个失恋状态,只需要让他增加一个失恋类,继承行为类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorOne
{
class UnLove : Action
{
public override void ManAction(Man man)
{
Console.WriteLine(man.GetType().Name + " 失恋 " + this.GetType().Name);
}
public override void WomanAction(Woman woman)
{
Console.WriteLine(woman.GetType().Name + " 失恋 " + this.GetType().Name);
}
}
}
四、代码实例二
实现账单的访问。
访问者类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Visitor_Bill
{
abstract class AccountView
{
public abstract void InView(InAccount account);
public abstract void OutView(OutAccount account);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Visitor_Bill
{
class Boss : AccountView
{
public override void InView(InAccount account)
{
Console.WriteLine(this.GetType().Name + " " + account.GetType().Name);
}
public override void OutView(OutAccount account)
{
Console.WriteLine(this.GetType().Name + " " + account.GetType().Name);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Visitor_Bill
{
class Secretary : AccountView
{
public override void InView(InAccount account)
{
Console.WriteLine(this.GetType().Name + " " + account.GetType().Name);
}
public override void OutView(OutAccount account)
{
Console.WriteLine(this.GetType().Name + " " + account.GetType().Name);
}
}
}
元素类,元素类为账单,只包含支出和收入,结构稳定
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Visitor_Bill
{
abstract class Account
{
public abstract void View(AccountView visitor_AccountView);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Visitor_Bill
{
class InAccount : Account
{
public override void View(AccountView visitor_AccountView)
{
visitor_AccountView.InView(this);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Visitor_Bill
{
class OutAccount : Account
{
public override void View(AccountView visitor_AccountView)
{
visitor_AccountView.OutView(this);
}
}
}
结构类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Visitor_Bill
{
class Structure
{
private List<Account> lists = new List<Account>();
public void Attach(Account account)
{
lists.Add(account);
}
public void Detach(Account account)
{
lists.Remove(account);
}
public void Viewing(AccountView accountView)
{
foreach (Account account in lists)
{
account.View(accountView);
}
}
}
}
测试
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Visitor_Bill
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Structure structure = new Structure();
structure.Attach(new InAccount());
structure.Attach(new OutAccount());
structure.Viewing(new Boss());
structure.Viewing(new Secretary());
}
}
}
五、代码实例三
扩展客户管理的功能(CRM)。 (节点)个人客户、企业客户。 (访问者)提出服务申请、客户价值分析、客户对产品偏好分析等。
访问者
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorCRM
{
abstract class Visitor
{
public abstract void VisitCompany(Company company);
public abstract void VisitPersonal(Personal personal);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorCRM
{
class Request : Visitor
{
public override void VisitCompany(Company company)
{
Console.WriteLine(company.GetType().Name+" "+this.GetType().Name);
}
public override void VisitPersonal(Personal personal)
{
Console.WriteLine(personal.GetType().Name + " " + this.GetType().Name);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorCRM
{
class Analyse : Visitor
{
public override void VisitCompany(Company company)
{
Console.WriteLine(company.GetType().Name + " " + this.GetType().Name);
}
public override void VisitPersonal(Personal personal)
{
Console.WriteLine(personal.GetType().Name + " " + this.GetType().Name);
}
}
}
节点类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorCRM
{
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorCRM
{
class Personal : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitPersonal(this);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VisitorCRM
{
class Company : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitCompany(this);
}
}
}
测试
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace VisitorCRM
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Request request = new Request();
Analyse analyse = new Analyse();
request.VisitCompany(new Company());
analyse.VisitCompany(new Company());
}
}
}
UML图
c#生成的不咋好看啊