原型模式: 当创建给定类的过程很昂贵或很复杂时, 就使用原型模式.
我们在进行游戏的时候游戏会动态创建怪, 而怪时根据场景的不同而变化创建的, 英雄自己也会创建一些随从. 创建各式各样的怪兽实例, 已经越来越麻烦, 将各种状态细节放再构造器中, 看起来一点都不内聚. 如果能够在单一区域内封装所有的实例化细节, 能够将负责处理创建怪兽的细节代码, 从实际需要动态创建实例的代码中解耦, 那么程序将变得相当干净.
原型模式通过复制现有的实例来创建新的实例, 通常使用 clone 方法, 或者反序列化.
设计类图:
原型模式中有三个角色:
原型角色: 定义用于复制现有实例来生成新实例的方法 (Monster).
具体原型角色: 实现用于复制现有实例来生成新实例的方法 (WellKnowMonster,DynamicGeneratedMonster).
使用者角色: 维护一个注册表, 并提供一个找出正确实例原型的方法. 最后, 提供一个获取新实例的方法, 用来委托复制实例的方法生成新实例.
实现代码:
1原型角色
- public interface Monster
- {
- public Monster Clone();
- }
2具体原型角色
- public class WellKnowMonster : Monster
- {
- public Monster Clone()
- {
- Monster clone = JsonConvert.DeserializeObject<WellKnowMonster>(JsonConvert.SerializeObject(this));
- return clone;
- }
- }
- public class DynamicGeneratedMonster : Monster
- {
- public Monster Clone()
- {
- Monster clone = JsonConvert.DeserializeObject<DynamicGeneratedMonster>(JsonConvert.SerializeObject(this));
- return clone;
- }
- }
3使用者角色
- public class MonsterRegistry
- {
- Dictionary<string, Monster> monsterDic = new Dictionary<string, Monster>();
- public void RegisterMonster(string key,Monster monster) {
- monsterDic.Add(key, monster);
- }
- public Monster GetMonster(string key) {
- Monster monster = monsterDic[key];
- return monster.Clone();
- }
- }
4测试
优点:
1, 向客户隐藏制造新实例的复杂性.
2, 提供让客户能够产生未知类型对象的选项.
3, 在某些环境下, 复制对象比创建新对象更有效.
用途和缺点:
1, 在一个复杂的类层次中, 当系统必须从许多类型创建新对象时, 可以考虑原型.
2, 使用原型模式的缺点, 对象的复制有时候相当复杂.
访问者
访问者模式: 当你想要为一个对象的组合增加新的能力, 且封装并不重要时, 就使用访问者模式.
当餐厅里面来了顾客, 可能顾客会询问菜单的信息 (比如这个辣不辣, 这个味道重不重之类的), 甚至有些会询问原材料的成分.
我们像这样设计在每个地方加入新方法, 如果增加了新方法我们就必须在两个地方加入新方法, 万一多了新的菜单我们就必须修改三个地方. 这种情况我们就可以使用访问者模式. 通过访问者访问组合内的每个元素, 收集组合中所有对象的状态. 一旦状态被收集了, 客户就可以让访问者对状态进行各种操作. 当需要新的功能时, 只要加强访问者即可.
实现代码:
1实现菜单, 菜单项接口定义 GetState 方法
- public interface MenuComponent
- {
- public void GetState(Visitor visitor);
- }
- // 菜单
- public class Menu : MenuComponent
- {
- public string displayInfo = "不辣, 口味适中";
- public void GetState(Visitor visitor)
- {
- visitor.Visit(this);
- }
- }
- // 原料
- public class Ingredients : MenuComponent
- {
- public string displayInfo = "不辣, 偏咸";
- public void GetState(Visitor visitor)
- {
- visitor.Visit(this);
- }
- }
2访问者, 访问者定义接口以便菜单项使用接口类型
- public interface Visitor
- {
- public void Visit(Menu menu);
- public void Visit(Ingredients ingredients);
- }
- class MenuVisitor : Visitor
- {
- public void Visit(Menu menu)
- {
- Console.WriteLine(menu.displayInfo);
- }
- public void Visit(Ingredients ingredients)
- {
- Console.WriteLine(ingredients.displayInfo);
- }
- }
3测试
优点:
1, 允许你对组合结构加入新的操作, 而无需改变结构本身.
2, 想加入新操作相对容易.
3, 访问者所进行的操作, 其代码是集中在一起的.
用途和缺点:
1, 当采用访问者模式的时候, 就会打破组合类的封装.
2, 因为访问模式的加入需要对每个像进行访问, 所以对组合结构的改变更加困难.
来源: https://www.cnblogs.com/SunSpring/p/12507777.html