• Head First设计模式——原型模式和访问者模式


    原型

    原型模式:当创建给定类的过程很昂贵或很复杂时,就使用原型模式。

    我们在进行游戏的时候游戏会动态创建怪,而怪时根据场景的不同而变化创建的,英雄自己也会创建一些随从。创建各式各样的怪兽实例,已经越来越麻烦,将各种状态细节放再构造器中,看起来一点都不内聚。如果能够在单一区域内封装所有的实例化细节,能够将负责处理创建怪兽的细节代码,从实际需要动态创建实例的代码中解耦,那么程序将变得相当干净。

    原型模式通过复制现有的实例来创建新的实例,通常使用clone方法,或者反序列化。

    设计类图:

    原型模式中有三个角色:

    原型角色:定义用于复制现有实例来生成新实例的方法(Monster)。

    具体原型角色:实现用于复制现有实例来生成新实例的方法(WellKnowMonster,DynamicGeneratedMonster)。

    使用者角色:维护一个注册表,并提供一个找出正确实例原型的方法。最后,提供一个获取新实例的方法,用来委托复制实例的方法生成新实例。

    实现代码:

    ①原型角色

    1     public interface Monster
    2     {
    3         public Monster Clone();
    4     }

    ②具体原型角色

     1     public class WellKnowMonster : Monster
     2     {
     3         public Monster Clone()
     4         {
     5             Monster clone = JsonConvert.DeserializeObject<WellKnowMonster>(JsonConvert.SerializeObject(this));
     6             return clone;
     7         }
     8     }
     9 
    10 
    11     public class DynamicGeneratedMonster : Monster
    12     {
    13         public Monster Clone()
    14         {
    15             Monster clone = JsonConvert.DeserializeObject<DynamicGeneratedMonster>(JsonConvert.SerializeObject(this));
    16             return clone;
    17         }
    18     }

    ③使用者角色

     1     public class MonsterRegistry
     2     {
     3         Dictionary<string, Monster> monsterDic = new Dictionary<string, Monster>();
     4         public void RegisterMonster(string key,Monster monster) {
     5             monsterDic.Add(key, monster);
     6         }
     7         public Monster GetMonster(string key) {
     8             Monster monster = monsterDic[key];
     9              return monster.Clone();
    10         }
    11     }

    ④测试

     优点:

    1、向客户隐藏制造新实例的复杂性。

    2、提供让客户能够产生未知类型对象的选项。

    3、在某些环境下,复制对象比创建新对象更有效。

    用途和缺点:

    1、在一个复杂的类层次中,当系统必须从许多类型创建新对象时,可以考虑原型。

    2、使用原型模式的缺点,对象的复制有时候相当复杂。

    访问者

    访问者模式:当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式。

    当餐厅里面来了顾客,可能顾客会询问菜单的信息(比如这个辣不辣,这个味道重不重之类的),甚至有些会询问原材料的成分。

    我们像这样设计在每个地方加入新方法,如果增加了新方法我们就必须在两个地方加入新方法,万一多了新的菜单我们就必须修改三个地方。这种情况我们就可以使用访问者模式。通过访问者访问组合内的每个元素,收集组合中所有对象的状态。一旦状态被收集了,客户就可以让访问者对状态进行各种操作。当需要新的功能时,只要加强访问者即可。

     实现代码:

    ①实现菜单,菜单项接口定义GetState方法

     1     public interface MenuComponent
     2     {
     3         public void GetState(Visitor visitor);
     4     }
     5 
     6 
     7     //菜单
     8     public class Menu : MenuComponent
     9     {
    10         public string displayInfo = "不辣,口味适中";
    11         public void GetState(Visitor visitor)
    12         {
    13             visitor.Visit(this);
    14         }
    15     }
    16 
    17     //原料
    18     public class Ingredients : MenuComponent
    19     {
    20         public string displayInfo = "不辣,偏咸";
    21         public void GetState(Visitor visitor)
    22         {
    23             visitor.Visit(this);
    24         }
    25     }

    ②访问者,访问者定义接口以便菜单项使用接口类型

        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);
            }
        }

    ③测试

    优点:

    1、允许你对组合结构加入新的操作,而无需改变结构本身。

    2、想加入新操作相对容易。

    3、访问者所进行的操作,其代码是集中在一起的。

    用途和缺点:

    1、当采用访问者模式的时候,就会打破组合类的封装。

    2、因为访问模式的加入需要对每个像进行访问,所以对组合结构的改变更加困难。

  • 相关阅读:
    Linux and the Unix Philosophy (Linux/Unix设计思想)
    rails获取json内容
    单元测试调试之传参篇
    部署注意细节之正式测试链接地址不同
    ajax页面排序的序号问题
    【51Nod1239】欧拉函数之和-杜教筛+哈希表
    【51Nod1239】欧拉函数之和-杜教筛+哈希表
    【51Nod1244】莫比乌斯函数之和-杜教筛+哈希表
    【51Nod1244】莫比乌斯函数之和-杜教筛+哈希表
    【BZOJ3112】防守战线(ZJOI2013)-单纯形法+对偶理论
  • 原文地址:https://www.cnblogs.com/SunSpring/p/12507777.html
Copyright © 2020-2023  润新知