Head First设计模式——原型模式和访问者模式
原型
原型模式:当创建给定类的过程很昂贵或很复杂时,就使用原型模式。
我们在进行游戏的时候游戏会动态创建怪,而怪时根据场景的不同而变化创建的,英雄自己也会创建一些随从。创建各式各样的怪兽实例,已经越来越麻烦,将各种状态细节放再构造器中,看起来一点都不内聚。如果能够在单一区域内封装所有的实例化细节,能够将负责处理创建怪兽的细节代码,从实际需要动态创建实例的代码中解耦,那么程序将变得相当干净。
原型模式通过复制现有的实例来创建新的实例,通常使用clone方法,或者反序列化。
设计类图:

原型模式中有三个角色:
原型角色:定义用于复制现有实例来生成新实例的方法(Monster)。
具体原型角色:实现用于复制现有实例来生成新实例的方法(WellKnowMonster,DynamicGeneratedMonster)。
使用者角色:维护一个注册表,并提供一个找出正确实例原型的方法。最后,提供一个获取新实例的方法,用来委托复制实例的方法生成新实例。
实现代码:
①原型角色
public interface Monster
{
public Monster Clone();
}
②具体原型角色
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;
}
}
③使用者角色
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();
}
}
④测试

优点:
1、向客户隐藏制造新实例的复杂性。
2、提供让客户能够产生未知类型对象的选项。
3、在某些环境下,复制对象比创建新对象更有效。
用途和缺点:
1、在一个复杂的类层次中,当系统必须从许多类型创建新对象时,可以考虑原型。
2、使用原型模式的缺点,对象的复制有时候相当复杂。
访问者
访问者模式:当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式。
当餐厅里面来了顾客,可能顾客会询问菜单的信息(比如这个辣不辣,这个味道重不重之类的),甚至有些会询问原材料的成分。

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

实现代码:
①实现菜单,菜单项接口定义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);
}
}
②访问者,访问者定义接口以便菜单项使用接口类型
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、因为访问模式的加入需要对每个像进行访问,所以对组合结构的改变更加困难。
Head First设计模式——原型模式和访问者模式的更多相关文章
- 【设计模式 - 24】之访问者模式(Visitor)
1 模式简介 访问者模式的定义: 访问者模式将数据结构与数据操作进行了分离,解决了稳定的数据结构和易变的数据操作的耦合问题. 访问者模式的优点: 1) 符合单一职责原则: 2) ...
- C#设计模式之二十一访问者模式(Visitor Pattern)【行为型】
一.引言 今天我们开始讲“行为型”设计模式的第九个模式,该模式是[访问者模式],英文名称是:Visitor Pattern.如果按老规矩,先从名称上来看看这个模式,我根本不能获得任何对理解该模式有用的 ...
- 设计模式23:Visitor 访问者模式(行为型模式)
Visitor 访问者模式(行为型模式) 动机(Motivation)在软件构造过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的修改,将会给子类带来繁重的 ...
- 设计模式-(13)访问者模式 (swift版)
一,概念 访问者模式,是行为型设计模式之一.访问者模式是一种将数据操作与数据结构分离的设计模式,它可以算是 23 中设计模式中最复杂的一个,但它的使用频率并不是很高,大多数情况下,你并不需要使用访问者 ...
- Java设计模式(23)——行为模式之访问者模式(Visitor)
一.概述 概念 作用于某个对象群中各个对象的操作.它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作. 引入 试想这样一个场景,在一个Collection中放入了一大堆的各种对象的引用 ...
- java设计模式9.备忘录模式、访问者模式、调停者模式
备忘录模式 备忘录模式又叫快照模式,备忘录对象是一个用来存储另外一个对象内部状态快照的对象.备忘录的用意是在不破坏封装的条件下,将一个对象的状态捕捉,并外部化存储起来,从而可以在将来合适的时候把这个对 ...
- 设计模式Design Pattern(4) -- 访问者模式
什么是访问者模式? 一个对象有稳定的数据结构,却为不同的访问者提供不同的数据操作,对象提供接收访问者的方法,从而保证数据结构的稳定性和操作的多样性.也可以理解为,封装对象的操作方法,达到不改变对象数据 ...
- 十一个行为模式之访问者模式(Visitor Pattern)
定义: 提供一个作用于某对象结构(通常是一个对象集合)的操作的接口,使得在添加新的操作或者在添加新的元素时,不需要修改原有系统,就可以对各个对象进行操作. 结构图: Visitor:抽象访问者类,对元 ...
- 行为型模式(九) 访问者模式(Visitor)
一.动机(Motivate) 在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设计.如何在不更 ...
随机推荐
- windows下的tfjs-node安装异常总结
大约有半年没有写博客了,奔波于上海这座魔都之中.险些忘了自己是个有梦想的全栈工程师 书接上回,由于个人非常厌恶python的语法,半年前发现了tensorflow.js这个宝贝(下简称tfjs),喜出 ...
- Heartbeat(注意iptables和selinux的问题)
安装 yum –y install heartbeat libnet配置 通过yum安装配置文件目录/etc/ha.d目录下没有配置文件需要从doc目录中复制三个文件.ha.cf.authkeys.h ...
- keepalive笔记之一:基本安装
在安装文件中有范例说明 /usr/share/doc/keepalived-1.2.13/samples/ Keepalived:它的诞生最初是为ipvs(一些服务,内核中的一些规则)提供高可用性的, ...
- mybatis的通用mapper小结
import tk.mybatis.mapper.entity.Example; //此包是tk下的1.定义一个dao层接口不需要任何方法 需要继承Mapper<类型> 2.在servic ...
- 烧钱时代终结!O2O还能玩啥花样?
最终的最终,饱受亏损.烧钱玩补贴等争议的美团还是追随滴滴/快的.赶集/58的步伐,与大众点评愉快的在一起了!美团和大众点评作为O2O行业的领军企业,都因为不堪忍受持续地投入却不见回报的模式而不得不放低 ...
- Opengl-法线贴图(用来细化表面的表现表现的凹凸)
我们通过这张图可以看出来,使用了法线贴图的物体表面更有细节更逼真,其实这就是发现贴图的作用,没什么钻牛角尖的. 其实表面没有凹凸的情况是因为我们把表面一直按照平整来做的,要想突出这个表面的凹凸就要用到 ...
- Jetson TX2镜像刷板法
使用Nvidia官方自带的脚本,备份镜像.恢复镜像,快速在新板子中部署DL环境 在之前的一篇博客中,详细介绍了使用JetPack刷系统以及使用离线包部署DL环境(cuda.cudnn.opencv.c ...
- AndroidManifest.xml文件详解
本文为安全专家李洋的最新一篇专栏文章<AndroidManifest.xml文件详解>.AndroidManifest.xml是一个跟安全相关的配置文件,该配置文件是Android安全保障 ...
- 从谷歌到脸书:为何巨头纷纷“钟情于”VR相机?
VR的火爆,自然无需多言.而基于VR这一个概念,已经在多个相关行业不断衍生出新的产品.服务或内容.VR眼镜.VR头盔.VR相机.VR游戏.VR影视.VR应用--但VR产业的发展并不是齐头并进,而是出现 ...
- js之构造函数的理解
在JavaScript中,创建对象的方式包括两种:对象字面量和使用new表达式.对象字面量是一种灵活方便的书写方式,例如: 1 2 3 4 5 6 var o1 = { p:”I’m in ...