40访问者模式(Visitor Pattern)

类层次结构的变化:
    类层次结构中可能经常由于引入新的操作,从而将类型变得脆弱...
                           
动机:
    在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设计。
    如何在不更改类层次结构的前提下,在运行时根据需要透明地为类层次结构上的各个类动态添加新的操作,从而避免上述问题?
意图:
    表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这引起元素的新操作。
结构:
             
适用性:

    1.一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
    2.需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作"污染"这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
    3.定义对象结构的类很少改变,但经常需要在结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
代码实现:
    

  1 // MainApp startup application
  2 
  3   class MainApp
  4   {
  5     static void Main()
  6     {
  7       // Setup employee collection
  8       Employees e = new Employees();
  9       e.Attach(new Clerk());
 10       e.Attach(new Director());
 11       e.Attach(new President());
 12 
 13       // Employees are 'visited'
 14       e.Accept(new IncomeVisitor());
 15       e.Accept(new VacationVisitor());
 16 
 17       // Wait for user
 18       Console.Read();
 19     }
 20   }
 21 
 22   // "Visitor"
 23 
 24   interface IVisitor
 25   {
 26     void Visit(Element element);
 27   }
 28 
 29   // "ConcreteVisitor1"
 30 
 31   class IncomeVisitor : IVisitor
 32   {
 33     public void Visit(Element element)
 34     {
 35       Employee employee = element as Employee;
 36 
 37       // Provide 10% pay raise
 38       employee.Income *= 1.10;
 39       Console.WriteLine("{0} {1}'s new income: {2:C}",
 40         employee.GetType().Name, employee.Name,
 41         employee.Income);
 42     }
 43   }
 44 
 45   // "ConcreteVisitor2"
 46 
 47   class VacationVisitor : IVisitor
 48   {
 49     public void Visit(Element element)
 50     {
 51       Employee employee = element as Employee;
 52       
 53       // Provide 3 extra vacation days
 54       Console.WriteLine("{0} {1}'s new vacation days: {2}",
 55         employee.GetType().Name, employee.Name,
 56         employee.VacationDays);
 57     }
 58   }
 59 
 60   class Clerk : Employee
 61   {
 62     // Constructor
 63     public Clerk() : base("Hank", 25000.0, 14)
 64     {
 65     }
 66   }
 67 
 68   class Director : Employee
 69   {
 70     // Constructor
 71     public Director() : base("Elly", 35000.0, 16)
 72     {  
 73     }
 74   }
 75 
 76   class President : Employee
 77   {
 78     // Constructor
 79     public President() : base("Dick", 45000.0, 21)
 80     {  
 81     }
 82   }
 83 
 84   // "Element"
 85 
 86   abstract class Element
 87   {
 88     public abstract void Accept(IVisitor visitor);
 89   }
 90 
 91   // "ConcreteElement"
 92 
 93   class Employee : Element
 94   {
 95     string name;
 96     double income;
 97     int vacationDays;
 98 
 99     // Constructor
100     public Employee(string name, double income,
101       int vacationDays)
102     {
103       this.name = name;
104       this.income = income;
105       this.vacationDays = vacationDays;
106     }
107 
108     // Properties
109     public string Name
110     {
111       get{ return name; }
112       set{ name = value; }
113     }
114 
115     public double Income
116     {
117       get{ return income; }
118       set{ income = value; }
119     }
120 
121     public int VacationDays
122     {
123       get{ return vacationDays; }
124       set{ vacationDays = value; }
125     }
126 
127     public override void Accept(IVisitor visitor)
128     {
129       visitor.Visit(this);
130     }
131   }
132 
133   // "ObjectStructure"
134 
135   class Employees
136   {
137     private ArrayList employees = new ArrayList();
138 
139     public void Attach(Employee employee)
140     {
141       employees.Add(employee);
142     }
143 
144     public void Detach(Employee employee)
145     {
146       employees.Remove(employee);
147     }
148 
149     public void Accept(IVisitor visitor)
150     {
151       foreach (Employee e in employees)
152       {
153         e.Accept(visitor);
154       }
155       Console.WriteLine();
156     }
157   }

运行结果:
       
Visoitr模式的几个要点:

    1.Visitor模式通过所谓双重分发(double dispatch)来实现在不更改Element类层次结构的前提下,在运行时透明地为类层次结构上的各个类动态添加新的操作。
    2.所谓双重分发却Visotor模式中间包括了两个多态分发(注意其中的多态机制);第一个为accept方法的多态辨析;第二个为visitor方法的多态辨析。
    3.Visotor模式的最大缺点在于扩展类层次结构(增添新的Element子类),会导致Visitor类的改变。因此Visiotr模式适用"Element"类层次结构稳定,而其中的操作却经常面临频繁改动".

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438624.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ssh中c3p0连接mysql_ssh 中使用c3p0 的连接池配置 | 学步园

applicationContext.xml 文件:xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns:jee"http://www.springframework.org/schema/jee"xsi:schemaLocation"http://www.springframework.org/schema/beans http://www.springframewor…

41状态模式(State Pattern)

对象状态影响对象行为: 对象拥有不同的状态,往往会行使不同的行为... 动机: 在软件构建过程中,某些对象的状态如果改变以及其行为也会随之而发生变化,比如文档处于只读状态,其支…

python中空格属于字符吗_举例说明python中空格是属于字符

python中空格属于字符吗?答案是肯定的,空格在Python中也是属于字符的。案例:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。#!/usr/bin/python# -*- coding: UTF-8 -*-import strings raw_input(input a st…

python如何引发和处理异常_在python3.6中,如何捕捉异常并引发异常以便稍后处理?...

假设我有两个例外:class FooError (Exception):def __init__(self, *args, **kwargs):default_message A foo error has occurred!if not (args or kwargs): args (default_message,)super().__init__(*args, **kwargs)class BarError (Exception):def __init__(s…

2字节十六进制浮点数 qt_Qt之8个字节转化为double小数

首先要理解double的存储方式,具体可查找相关的博客本文实现的是将8个字节(存储为16进制的字符串)转化为对应的double类型double MainWindow::qByteArraytodouble(QString qstr){QByteArray byte;StringToHex(qstr,byte);double result;memcpy(&result, byte.dat…

【转】如何将域中的AD数据导入SharePoint

最近刚装好sharepoint2010,想要研究一下,第一件想做的事就是想把AD中的用户信息导入到SharePoint中。 那现在就来看看我是怎么操作的: 1.打开管理中心 sharepoint是通过“用户配置文件同步服务”来实现同步,所以第一步要开启这个…

Apsara Clouder专项技能认证:实现调用API接口

一.API 简介 1.API 的概念 API(Application Programming Interface应用程序编程接口)是一些预定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码或理解内部工作机制的细节 2.API 的特点 API 是一个明确定义的接口,可以为其…

druid加密mysql_Druid 数据库用户密码加密 代码实现

标签:druid-1.0.16.jar 阿里巴巴的开源数据连接池 jar包明文密码私钥(privateKey)加密加密密码加密密码公钥(publicKey)解密明文密码程序代码如下:package com.t1;import com.alibaba.druid.filter.config.ConfigTools;public class DruidTest {public s…

select switch语句总是搞混,总结如下

select switch语句总是搞混,总结如下 类C:c c c# java : 比较 switch(expression) { case constant-expression : statement(s); break; /* optional */ case constant-expression : statement(s); brea…

java路径怎么找_Java路径怎么找

有一种情况是装好java了,配置好java环境(在Linux里面比较复杂)了,但忘了路径了?!解决:先要申明一下which java是定位不到安装路径的。which java定位到的是java程序的执行路径。网上的资料都是人云亦云,完全…

【转】什么是CORS

CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 AJAX 跨域请求资源的方式,支持现代浏览器,IE支持10以上。 CORS与JSONP的使用目的相同,但是比JSONP更强大。JSONP只支持GET请求&#xff0c…

java web 连接linux_如何将javaweb项目部署到linux下

以下是对将javaweb项目部署到linux下的方法进行了详细的分析介绍一般都在windows下开发的现在部署到linux下将项目达成war包(用eclipse项目右键>Export>选择war file)将tomcat(用winSCP当然你也可以用secureCRT用securCRT需要建立sftp(即上传文件的目录)用put tomcat命令…

第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待

一. 再谈委托 1. 委托是一个关键字为delegate的自定义类型,通过委托可以把方法以参数的形式传递给另外一个方法,实现插件式的开发模式; 同时调用委托的时候,委托所包含的所有方法都会被实现。 2. 委托的发展历史:new…

linux 修改 java 内存_Linux 和 Windows修改Java虚拟机内存大小

因为内存溢出问题1. Linux下直接修改%tomcat_home%/bin/catalina.sh文件在注释下紧接一行也就是脚本正文开始之前 加上Java_OPTS-server -Xms512m -Xmx1024m -XX:PermSize128m -XX:MaxPermSize512m如果报-x没有定义,则用declare -x JAVA_OPTS"-Xms512m -Xmx1024"初始…

第二节:深入剖析Thread的五大方法、数据槽、内存栅栏

一. Thread及其五大方法 Thread是.Net最早的多线程处理方式,它出现在.Net1.0时代,虽然现在已逐渐被微软所抛弃,微软强烈推荐使用Task(后面章节介绍),但从多线程完整性的角度上来说,我们有必要了解下N年前多线程的是怎么…

java redis 生成唯一id_Redis在集群环境中生成唯一ID

概述设计目标:每秒最大生成10万个ID,ID单调递增且唯一。Reidis可以不需要持久化ID。要求:集群时钟不能倒退。总体思路:集群中每个节点预生成生成ID;然后与redis的已经存在的ID做比较。如果大于,则取节点生成的ID&#…

java 读取 image_如何在java读取sql里头读取image格式的数据转换成图片格式

一、北亚文件系统数据恢复Windows版可以恢复Windows用户在使用过程中丢失的数据(误删除文件、误格式化硬盘、U盘/手机存储卡数据丢失、误清空回收站、磁盘分区消失)。软件操作简单,易用。可恢复故障:误删除文件:1:可只恢复指定路径…

java await signal_【Java并发008】原理层面:ReentrantLock中 await()、signal()/signalAll()全解析...

一、前言上篇的文章中我们介绍了AQS源码中lock方法和unlock方法,这两个方法主要是用来解决并发中互斥的问题,这篇文章我们主要介绍AQS中用来解决线程同步问题的await方法、signal方法和signalAll方法,这几个方法主要对应的是synchronized中的…

java 抽象类构造函数_抽象类可以有构造函数吗?

是的,抽象类可以有构造函数。考虑到这一点:abstract class Product {int multiplyBy;public Product( int multiplyBy ) {this.multiplyBy multiplyBy;}public int mutiply(int val) {return multiplyBy * val;}}class TimesTwo extends Product {publi…

java 动态生成证书_android平台使用java动态生成公私钥,并导出证书文件

不依赖keytool工具,指令生成证书库,而是java代码生成,且导出到证书文件中。直接上代码:证书工具类:package com.daobo.security.utilsimport com.daobo.security.bean.Certificationimport org.bouncycastle.jce.provi…