学习而来,代码是自己敲的。也有些自己的理解在里边,有问题希望大家指出。

行为型模式,我之所以把他放到第一个,是因为它号称是GoF中最难的一个。

模式的定义与特点

访问者模式中(Visitor Pattern)中,我们使用了一个访问者类,他改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。根据访问者模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

模式的优点

  • 符合单一职责原则。
  • 拥有优秀的扩展性。
  • 非常灵活。

模式的缺点

  • 具体元素对访问者公布细节,违反了迪米特法则。
  • 具体元素变更比较困难。
  • 依赖了具体类,没有依赖抽象,这违反了依赖倒置原则。

举例使用场景

说在某个厨师交流会上,有三个人一拍即合要开餐馆。这三个人分别是一个老板、一个中国厨师、一个西方厨师。餐馆开起来后客人络绎不绝,但两位厨师用的没油了,提出要加服务员跑腿。老板不同意啊,多一个人就得多开钱啊,于是让两位厨师自行解决。并且说不管是这次的油,还是之后还有别的需求都让两个厨师自己解决。

分析故事:永远只有三个人,所有事情都需要两个厨师自己解决。

想到的解决办法:

  • 更改厨师类,新增获取油或者是其他需求时,进行类的扩展,这样不符合开闭原则
  • 抽象厨师类,每次有新的需求时新增一个厨师就行,这样看似符合开闭原则,且解决了问题,但题目内容本身,是不允许新增员工的。
  • 被制作的东西告诉厨师:"1、你需要做我。2、我是你怎么做出来的 ",然后厨师做出了这个东西。这样之后厨师需要做什么,原有代码都不需要修改,只需要增加被生产的内容类即可。这样符合开闭原则,也完美的解决了问题。

根据题目与结论得出,应该有俩厨师类一个被生产类

俩厨师类来做东西(访问者),通过访问者:“1:告知厨师类需求做出自己,2:告知厨师类怎么制作自己”。

internal class Program {
static void Main(string[] args) {
List<Cooker> cookers = new List<Cooker>() { //获取所有厨师
new ChineseChef(),
new WesternChef(),
};
Visitor meat = new MeatVisitor(); //获取肉类访问者
Visitor oil = new GetOilVisitor(); //获取油类访问者
for (int i = cookers.Count - 1; i >= 0; i--) {
//cookers[i].Cooking(meat); //告诉厨师需要做什么内容(肉)
cookers[i].Cooking(oil); //告诉厨师需要做什么内容(油)
}
Console.ReadLine();
}
}
//===================================================================================================
internal abstract class Cooker { //厨师抽象类
public string Name; //厨师
public abstract void Cooking(Visitor visitors); //抽象出做东西 参数:做的内容(访问者)
}
internal class ChineseChef : Cooker {
public override void Cooking(Visitor visitors) {
Name = "中国厨师";
visitors.Chinesechef(this); //告诉访问者,现在是中国厨师在做
}
}
internal class WesternChef : Cooker {
public override void Cooking(Visitor visitors){
Name = "西方厨师";
visitors.Westernchef(this); //告诉访问者,现在是西方厨师在做
}
}
//===================================================================================================
internal abstract class Visitor { //访问者类抽象
public abstract void Chinesechef(Cooker cookers); //抽象出 中国厨师怎么做自己
public abstract void Westernchef(Cooker cookers); //抽象出 西方厨师怎么做自己
}
internal class MeatVisitor : Visitor { //定义访问者自身为肉
public override void Chinesechef(Cooker cookers) { //告诉中国厨师自己怎么做
Console.WriteLine($"{cookers.Name}认为,肉 要煮的吃");
//Console.WriteLine("中国厨师认为,肉 要煮的吃");
}
public override void Westernchef(Cooker cookers) { //告诉西方厨师自己怎么做
Console.WriteLine($"{cookers.Name}认为,肉 要煎的吃");
//Console.WriteLine("西方厨师认为,肉 要煎的吃");
}
}
internal class GetOilVisitor : Visitor {
public override void Chinesechef(Cooker cookers) {
Console.WriteLine($"{cookers.Name}认为,油 可以通过肉炼出来");
//Console.WriteLine("中国厨师认为,油 可以通过肉炼出来");
}
public override void Westernchef(Cooker cookers) {
Console.WriteLine($"{cookers.Name}认为,油 应该去超市买");
//Console.WriteLine("西方厨师认为,油 应该去超市买");
}
}


希望大家:点赞,留言,关注咯~

唠家常

今日分享结束啦,小伙伴们你们get到了么,你们有没有更好的办法呢,可以评论区留言分享,也可以加QQ:841298494,大家一起进步。

  • 客官,看完get之后记得点赞哟!
  • 小伙伴你还想要别的知识?好的呀,分享给你们

今日推荐

最新文章

  1. NSAttributedString字符串属性类
  2. template学习一函数模板
  3. Windows Azure HandBook (7) 基于Azure Web App的企业官网改造
  4. 手机自带的显示基站命令(android手机定位,iphone基站定位)
  5. tp auth 转载保存
  6. [JS]Cookie精通之路
  7. 系统默认字体Mac OS,Windows,XP,Lunix
  8. NOR和NAND flash区别,RAM 和ROM区别
  9. error C3872: “0x3000”: 此字符不允许在标识符中使用
  10. Spring学习(8)--- @Autowired注解(一)
  11. JavaScript 加号运算符详解
  12. C#的dapper使用
  13. 航班座位_hihocoder
  14. 颜色(color)透明
  15. Socket 实现聊天功能
  16. HDFS 的垃圾回收配置
  17. 第 8 章 容器网络 - 058 - flannel 概述
  18. Oracle 12C -- 网络性能调优
  19. Android Studio SVN使用
  20. matlab中将矩阵按照行打乱顺序的一个例子

热门文章

  1. Java Timer使用介绍
  2. Python处理刚刚,分钟,小时,天前等时间
  3. HPL Study 2
  4. python 队列(QUEUE)
  5. git ignore忽略规则
  6. 核磁共振成像学习笔记——从FID信号到K空间
  7. 小程序canvas2D绘制印章,话不多说,直接上代码
  8. 教你用JavaScript完成轮播图
  9. 乐维监控与Zabbix对比分析(一)——架构、性能
  10. Springboot优雅进行字段检验