学习而来,代码是自己敲的。也有些自己的理解在里边,有问题希望大家指出。
行为型模式,我之所以把他放到第一个,是因为它号称是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,大家一起进步。
- 博客杂货铺
- GoF23 种设计模式的分类和功能