• 行为型模式 - 访问者模式Visitor


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

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

     

    模式的定义与特点

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

    模式的优点

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

    模式的缺点

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

    举例使用场景

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

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

    想到的解决办法:

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

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

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

    1. internal class Program {
    2. static void Main(string[] args) {
    3. List cookers = new List() { //获取所有厨师
    4. new ChineseChef(),
    5. new WesternChef(),
    6. };
    7. Visitor meat = new MeatVisitor(); //获取肉类访问者
    8. Visitor oil = new GetOilVisitor(); //获取油类访问者
    9. for (int i = cookers.Count - 1; i >= 0; i--) {
    10. //cookers[i].Cooking(meat); //告诉厨师需要做什么内容(肉)
    11. cookers[i].Cooking(oil); //告诉厨师需要做什么内容(油)
    12. }
    13. Console.ReadLine();
    14. }
    15. }
    16. //===================================================================================================
    17. internal abstract class Cooker { //厨师抽象类
    18. public string Name; //厨师
    19. public abstract void Cooking(Visitor visitors); //抽象出做东西 参数:做的内容(访问者)
    20. }
    21. internal class ChineseChef : Cooker {
    22. public override void Cooking(Visitor visitors) {
    23. Name = "中国厨师";
    24. visitors.Chinesechef(this); //告诉访问者,现在是中国厨师在做
    25. }
    26. }
    27. internal class WesternChef : Cooker {
    28. public override void Cooking(Visitor visitors){
    29. Name = "西方厨师";
    30. visitors.Westernchef(this); //告诉访问者,现在是西方厨师在做
    31. }
    32. }
    33. //===================================================================================================
    34. internal abstract class Visitor { //访问者类抽象
    35. public abstract void Chinesechef(Cooker cookers); //抽象出 中国厨师怎么做自己
    36. public abstract void Westernchef(Cooker cookers); //抽象出 西方厨师怎么做自己
    37. }
    38. internal class MeatVisitor : Visitor { //定义访问者自身为肉
    39. public override void Chinesechef(Cooker cookers) { //告诉中国厨师自己怎么做
    40. Console.WriteLine($"{cookers.Name}认为,肉 要煮的吃");
    41. //Console.WriteLine("中国厨师认为,肉 要煮的吃");
    42. }
    43. public override void Westernchef(Cooker cookers) { //告诉西方厨师自己怎么做
    44. Console.WriteLine($"{cookers.Name}认为,肉 要煎的吃");
    45. //Console.WriteLine("西方厨师认为,肉 要煎的吃");
    46. }
    47. }
    48. internal class GetOilVisitor : Visitor {
    49. public override void Chinesechef(Cooker cookers) {
    50. Console.WriteLine($"{cookers.Name}认为,油 可以通过肉炼出来");
    51. //Console.WriteLine("中国厨师认为,油 可以通过肉炼出来");
    52. }
    53. public override void Westernchef(Cooker cookers) {
    54. Console.WriteLine($"{cookers.Name}认为,油 应该去超市买");
    55. //Console.WriteLine("西方厨师认为,油 应该去超市买");
    56. }
    57. }


     

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

    唠家常

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

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

    今日推荐

  • 相关阅读:
    YOLOv5 环境搭建
    不标准的 json 格式的字符串如何转为标准的(json字符串属性名不带双引号如何转
    递归-汉罗塔及其变种
    pat basic 1050 螺旋矩阵
    PVE虚拟机下如何安装自定义备份Win系统镜像文件
    【组成原理 六 存储器类型】
    JAVA this关键词作用
    企业知识库系统:从0开始,部署企业知识库模型
    ES7~ES12那些事儿
    Jenkins :添加node权限获取凭据、执行命令
  • 原文地址:https://blog.csdn.net/Wenhao_China/article/details/128214649