设计模式——访问者模式

Posted cwmizlp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式——访问者模式相关的知识,希望对你有一定的参考价值。

 

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

 

参与者

Visitor       抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
ConcreteVisitor.       具体访问者角色,实现Visitor声明的接口。
Element        定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
ConcreteElement        具体元素,实现了抽象元素(Element)所定义的接受操作接口。
ObjectStructure       结构对象角色,这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。

 

适用性

  • 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。

 

在生活中,我们要去医院看病,当我们挂号找到主治医生的医生看完病以后,会给你开一张药单,这个时候你需要先去付费,由划价医生收取药费,然后你拿着付费单再去找抓药师抓药。传统上我们也许会,写一个划价师类,里面根据药的名称做判断收取多少费用;写一个抓药师根据药单上面名称要判断去哪里抓药。可能使用Switch进行判断,这样增加了药就要改变划价人员和药房工作者的代码。

访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式,这就是访问者模式的模式动机。

 

 

 1 /// <summary>  
 2 /// 抽象访问者  
 3 /// </summary>  
 4 public abstract class Visitor  
 5 {  
 6     protected string name { get; set; }  
 7   
 8     public Visitor(string name)  
 9     {  
10         this.name = name;  
11     }  
12   
13     public abstract void visitor(MedicineA a);  
14   
15     public abstract void visitor(MedicineB b);  
16 }  

 

 

 1 /// <summary>  
 2 /// 具体访问者:划价员  
 3 /// </summary>  
 4 public class Charger :Visitor  
 5 {  
 6     public Charger(string name) : base(name) { }  
 7   
 8     public override void visitor(MedicineA a)  
 9     {  
10         Console.WriteLine("划价员:"+this.name+"给药"+a.GetName()+"价格:"+a.GetPrice());  
11     }  
12   
13     public override void visitor(MedicineB b)  
14     {  
15         Console.WriteLine("划价员:" + this.name + "给药" + b.GetName() + "价格:" + b.GetPrice());  
16     }  
17 }  

 

 

 1 /// <summary>  
 2 /// 具体访问者:药房工作者  
 3 /// </summary>  
 4 public class WorkerOfPharmacy:Visitor  
 5 {  
 6     public WorkerOfPharmacy(string name) : base(name) { }  
 7     public override void visitor(MedicineA a)  
 8     {  
 9         Console.WriteLine("药房工作者:"+this.name+",拿药:"+a.GetName());  
10     }  
11   
12     public override void visitor(MedicineB b)  
13     {  
14         Console.WriteLine("药房工作者:" + this.name + ",拿药:" + b.GetName());  
15     }  
16 }  

 

 

 1 /// <summary>  
 2 /// 抽象元素:药  
 3 /// </summary>  
 4 public abstract class Medicine  
 5 {  
 6     protected string name { get; set; }  
 7     protected double price { get; set; }  
 8   
 9     public Medicine(string name, double price)  
10     {  
11         this.name = name;  
12         this.price = price;  
13     }  
14   
15     public string GetName()  
16     {  
17         return name;  
18     }  
19   
20     public double GetPrice()  
21     {  
22         return price;  
23     }  
24   
25     public void SetPrice(double price)  
26     {  
27         this.price = price;  
28     }  
29   
30     public abstract void accept(Visitor visitor);  
31 }  

 

 

 1 /// <summary>  
 2 /// 具体元素:A名称药  
 3 /// </summary>  
 4 public  class MedicineA:Medicine  
 5 {  
 6     public MedicineA(string name, double price) : base(name, price) { }  
 7   
 8     public override void accept(Visitor visitor)  
 9     {  
10         visitor.visitor(this);  
11     }  
12 }  

 

 

 1 /// <summary>  
 2 /// 具体元素:B名称药  
 3 /// </summary>  
 4 public class MedicineB:Medicine  
 5 {  
 6     public MedicineB(string name, double price) : base(name, price) { }  
 7   
 8     public override void accept(Visitor visitor)  
 9     {  
10         visitor.visitor(this);  
11     }  
12 }  

 

 

 1 /// <summary>  
 2 /// 具体元素:药单  
 3 /// </summary>  
 4 public class Presciption  
 5 {  
 6     private List<Medicine> listmedicine = new List<Medicine>();  
 7     public void accpet(Visitor visitor)  
 8     {  
 9         foreach (var item in listmedicine)  
10         {  
11             item.accept(visitor);  
12         }  
13     }  
14   
15     public void add(Medicine med)  
16     {  
17         listmedicine.Add(med);  
18     }  
19   
20     public void remove(Medicine med)  
21     {  
22         listmedicine.Remove(med);  
23     }  
24 }  

 

 

 1 /// <summary>  
 2 /// C#设计模式-访问者模式  
 3 /// </summary>  
 4 class Program  
 5 {  
 6     static void Main(string[] args)  
 7     {  
 8         //药类型  
 9         Medicine a = new MedicineA("药A", 10);  
10         MedicineB b = new MedicineB("药B", 20);  
11   
12         //药单  
13         Presciption presciption = new Presciption();  
14         presciption.add(a);  
15         presciption.add(b);  
16   
17         Visitor charger = new Charger("张三");    //划价员  
18         Visitor workerOfPharmacy = new WorkerOfPharmacy("李四"); //抓药员  
19   
20         presciption.accpet(charger); //划价  
21         Console.WriteLine();  
22         presciption.accpet(workerOfPharmacy); //抓药  
23     }  
24 }  

 

 

访问者模式是用来封装一些施加于某种数据结构之上的操作。它使得可以在不改变元素本身的前提下增加作用于这些元素的新操作,访问者模式的目的是把操作从数据结构中分离出来。

 

 

学习于     https://blog.csdn.net/heyangyi_19940703/article/details/51374416





以上是关于设计模式——访问者模式的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用片段保存夜间模式状态

从 Viewpager2 片段访问父片段函数

csharp C#代码片段 - 使类成为Singleton模式。 (C#4.0+)https://heiswayi.github.io/2016/simple-singleton-pattern-us

在不存在的片段上调用片段生命周期和 onCreate 的问题

java 查看寻呼机设计模式与片段。

如何仅将应用程序片段设置为纵向模式?