①基本介绍
②男人和女人
③访问者模式的优缺点
④适用场景
访问者模式:提供一个作用于某对象结构中的各元素的操作表示,它使得可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
访问者模式是一种较为复杂的行为型设计模式,它包含访问者与被访问者两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。
访问者模式5个角色
①Visitor(抽象访问者):为每一个具体元素类声明一个具体访问者的操作。
②ConcreteVisitor(具体访问者):实现抽象访问者中的操作。
③Element(抽象元素):接口/抽象类,定义一个accept方法表示接受访问者的访问。
④ConcreteElement(具体元素):实现了accept方法,在accept中调用访问者的访问方法完成对具体元素的访问。
⑤ObjectStructure(对象结构):抽象元素的集合,用于存放抽象元素对象,提供了遍历内部元素的方法。
这都是啥呀,好好撸码不香吗
static void Main(string[] args)
{
{
Console.WriteLine("男人成功时,背后多半有一个伟大的女人。");
Console.WriteLine("女人成功时,背后大多有一个不成功的男人。");
Console.WriteLine("男人失败时,闷头喝酒,谁也不用劝。");
Console.WriteLine("女人失败时,眼泪汪汪,谁也劝不了。");
Console.WriteLine("男人恋爱时,凡事不懂也要装懂。");
Console.WriteLine("女人恋爱时,遇事懂也装作不懂。");
}
}
分析:不解释,初级程序员干的事情,小菜菜。
①抽象类,男人与女人
public abstract class Person
{
public string Action { get; set; }
public abstract void GetConclusion();
}
public class Man : Person
{
public override void GetConclusion()
{
if (Action == "成功")
{
Console.WriteLine($"{this.GetType().Name}{Action}时,背后大多有一个不成功的男人。");
}
else if (Action == "失败")
{
Console.WriteLine($"{this.GetType().Name}{Action}时,闷头喝酒,谁也不用劝。");
}
else if (Action == "恋爱")
{
Console.WriteLine($"{this.GetType().Name}{Action}时,凡事不懂也要装懂。");
}
}
}
public class WoMan : Person
{
public override void GetConclusion()
{
if (Action == "成功")
{
Console.WriteLine($"{this.GetType().Name}{Action}时,背后多半有一个伟大的女人。");
}
else if (Action == "失败")
{
Console.WriteLine($"{this.GetType().Name}{Action}时,眼泪汪汪,谁也劝不了。");
}
else if (Action == "恋爱")
{
Console.WriteLine($"{this.GetType().Name}{Action}时,遇事懂也装作不懂。");
}
}
}
②上端调用
static void Main(string[] args)
{
var listPerson = new List();
Person man1 = new Man();
man1.Action = "成功";
listPerson.Add(man1);
Person woman1 = new WoMan();
woman1.Action = "成功";
listPerson.Add(woman1);
Person man2 = new Man();
man2.Action = "失败";
listPerson.Add(man2);
Person woman2 = new WoMan();
woman2.Action = "失败";
listPerson.Add(woman2);
Person man3 = new Man();
man3.Action = "恋爱";
listPerson.Add(man3);
Person woman3 = new WoMan();
woman3.Action = "恋爱";
listPerson.Add(woman3);
foreach (var item in listPerson)
{
item.GetConclusion();
}
}
分析:总算算是面向对象编程了,但是GetConclusion中职责逻辑过多,如果再添加一种状态,是否又需要添加一个ifelse呢
①状态抽象类与人的抽象类
public abstract class Action
{
public abstract void GetManConclusion(Man concreteElementA);
public abstract void GetWoManConclusion(WoMan concreteElementB);
}
public abstract class Person
{
public abstract void Accept(Action visitor);
}
②具体状态类
public class Success : Action
{
public override void GetManConclusion(Man concreteElementA)
{
Console.WriteLine($"{concreteElementA.GetType().Name}{this.GetType().Name}时,背后多半有一个伟大的女人。");
}
public override void GetWoManConclusion(WoMan concreteElementB)
{
Console.WriteLine($"{concreteElementB.GetType().Name}{this.GetType().Name}时,背后大多有一个不成功的男人。");
}
}
public class Failing : Action
{
public override void GetManConclusion(Man concreteElementA)
{
Console.WriteLine($"{concreteElementA.GetType().Name}{this.GetType().Name}时,闷头喝酒,谁也不用劝。");
}
public override void GetWoManConclusion(WoMan concreteElementB)
{
Console.WriteLine($"{concreteElementB.GetType().Name}{this.GetType().Name}时,眼泪汪汪,谁也劝不了。");
}
}
public class Loving : Action
{
public override void GetManConclusion(Man concreteElementA)
{
Console.WriteLine($"{concreteElementA.GetType().Name}{this.GetType().Name}时,凡事不懂也要装懂。");
}
public override void GetWoManConclusion(WoMan concreteElementB)
{
Console.WriteLine($"{concreteElementB.GetType().Name}{this.GetType().Name}时,遇事懂也装作不懂。");
}
}
③男人和女人类实现
public class Man : Person
{
public override void Accept(Action visitor)
{
visitor.GetManConclusion(this);
}
}
public class WoMan : Person
{
public override void Accept(Action visitor)
{
visitor.GetWoManConclusion(this);
}
}
④对象结构
public class ObjectStructure
{
private List listPerson = new List();
//增加
public void Attach(Person person)
{
listPerson.Add(person);
}
//移除
public void Detach(Person person)
{
listPerson.Remove(person); ;
}
//查看显示
public void Display(Action visitor)
{
foreach (var item in listPerson)
{
item.Accept(visitor);
}
}
}
⑤上端调用
static void Main(string[] args)
{
ObjectStructure o = new ObjectStructure();
o.Attach(new Man());
o.Attach(new WoMan());
Action v1 = new Success();
o.Display(v1);
Action v2 = new Failing();
o.Display(v2);
Action v3 = new Loving();
o.Display(v3);
}
分析:经过拆解每个类的职责都很明确,如果我们此时添加了一个结婚状态呢?只需要添加一个结婚的状态类继承于Action,上端直接调用即可。完美的体现了开闭原则。
①新增访问操作方便
使用访问者模式,增加新的访问操作就意味着增加一个新的具体访问者类,实现简单,符合开闭原则。
②集中访问行为
将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中,类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。
①新增元素类困难
访问者模式中每新增一个元素类以为着抽象访问者角色需要增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,违背了开闭原则。
②破坏封装
访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。
①一个对象结构中包含多个类型的对象,希望对这些对象实施一些依赖其具体类型的操作。在访问者中针对每一种具体类型都提供了一个访问操作,不同类型的对象可以有不同的访问操作。
②需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而且需要避免让这些操作“污染”这些对象的类,也不希望在新增操作时修改这些类。访问者模式将相关的访问操作集中起来定义在访问者类中,对象结构可以被多个不同的访问者者类所使用,将对象本身于对象的访问操作分离。
③对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作