行为型模式 - 访问者模式Visitor
创始人
2024-03-23 14:31:18
0次

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

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

 

模式的定义与特点

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

模式的优点

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

模式的缺点

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

举例使用场景

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

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

想到的解决办法:

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

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

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

internal class Program {static void Main(string[] args) {List cookers = new List() {           //获取所有厨师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之后记得点赞哟!
  • 小伙伴你还想要别的知识?好的呀,分享给你们😄

今日推荐

  • 博客杂货铺
  • GoF23 种设计模式的分类和功能

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...