大话设计模式(带目录完整版)[中文PDF+源代码].zip

下载地址:http://pan.baidu.com/s/1giQP4
大话设计模式C++.pdf
下载地址:http://pan.baidu.com/s/1ABbBv
大话设计模式C++源码

下载地址:http://pan.baidu.com/s/1yzLBl

----------------------------------------------
刚刚看了访问者模式,复杂问题简单化。
class Node
{
 accept(Visitro *pVisitor);
}
class Visitor

{

apply(Node *pNode){pNode->fun();}

}

------------------------------------------------
url:http://greatverve.cnblogs.com/p/Design-patterns-down.html

访问者模式的目的:  封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。

问题的提出:System.Collection命名空间下提供了大量集合操作对象。平时我们大多在集合中都是存储的同类型对象,像2.0中的泛型中就规定集合中只能存储指定的对象类型,要么是整形要么是字符型等,否则会报错。如果针对一个保存有不同类型对象的聚集采取某种操作该怎么办呢?

示例:假设有一个员工报销的集合,里面存储了员工姓名和报销金额情况,而报销数据类型并不统一,有的是整形的,有的是双精度的,有的是字符串型,我们要做的就是根据具体的数据类型给出不同的显示格式,例如在整型数据后面加一个"C",(是我自己想的,整型的符号一时没想起来),在双数度数据后面加一个"D",浮点数据后面加"F",而字符串则什么也不加。

传统实现方式:遍历集合中的元素,判断元素类型,然后做相应的处理。代码如下:会发现就会出现必须对元素类型做类型判断的条件转移语句,如果判断多了,要想维护起来也并不容易。此时可考虑采用访问者模式。

ArrayList _arr = new ArrayList();
            _arr.Add("一百元");
            _arr.Add(100);
            _arr.Add(150.5);
            foreach  (object o in _arr )
            {
                if (o is string)
                {
                    Console.WriteLine(o.ToString());
                }
                else if (o is double)
                {
                    Console .WriteLine (o.ToString ()+" D");
                }
                else if (o is Int32)
                {
                    Console.WriteLine(o.ToString()+" C");
                }
            
            }

访问者模式适用性:

1:数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
           2:被访问的类结构非常稳定的情况下使用。系统很少出现需要加入新节点的情况。如果出现需要加入新节点的情况,那么就必须在每一个访问对象里加入一个对应于这个新节点的访问操作,而这是对一个系统的大规模修改,因而是违背"开一闭"原则的。

访问者模式的结构:

1:抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。

/// <summary>
    /// 抽象访问者(Visitor)角色
    /// </summary>
    abstract class Visitor
    {
        // Methods
        abstract public void Visit(Element element);
    }

2:具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。

/// <summary>
    /// 具体访问者(ConcreteVisitor)角色
    /// 打印双精度数据
    /// 在数据后面加 D
    /// </summary>
    class DoubleVisitor : Visitor
    {
        // Methods
        public override void Visit(Element element)
        {
            Employee employee = ((Employee)element);
            if (employee._Data.GetType().ToString ()!="System.Double")
            { return; }
            Console.WriteLine("{0}'s data: {1}D",
              employee.Name, employee._Data );
        }
    }
    /// <summary>
    /// 具体访问者(ConcreteVisitor)角色2
    /// 打印整型数据
    /// 在数据后面加 C
    /// </summary>
    class Int32Visitor : Visitor
    {
        public override void Visit(Element element)
        {        
            Employee employee = ((Employee)element);
            if (employee._Data.GetType().ToString() != "System.Int32")
            { return; }
            Console.WriteLine("{0}'s data : {1}C",
              employee.Name, employee._Data );
        }
    }

3:抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参量。

/// <summary>
    /// 抽象节点(Node)角色
    /// </summary>
    abstract class Element
    {
        // Methods
        abstract public void Accept(Visitor visitor);
    }

4:具体节点(Node)角色:实现了抽象元素所规定的接受操作。

/// <summary>
    /// 具体节点(Node)角色
    /// </summary>
    class Employee : Element
    {
        // Fields
        string name;
        private object  _data;
        public object  _Data
        {
            get { return this._data ; }
            set { this._data  = value; }
        }
        // Constructors
        public Employee(string _name,object  t)
        {
            this.name = _name;
            this._Data  = t;
            
        }
        // Properties
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        // Methods
        public override void Accept(Visitor visitor)
        {
            visitor.Visit(this);
        }
    }

5:结构对象(ObiectStructure)角色:有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集。

/// <summary>
    /// 结构对象(ObiectStructure)角色
    /// </summary>
    class Employees
    {
        // Fields
        private ArrayList employees = new ArrayList();
        // Methods
        public void Attach(Employee employee)
        {
            employees.Add(employee);
        }

public void Detach(Employee employee)
        {
            employees.Remove(employee);
        }
        public void Accept(Visitor visitor)
        {
            foreach (Employee e in employees)
                e.Accept(visitor);
        }
    }

6:客户端代码:

// Setup employee collection
            Employees e = new Employees();
            e.Attach(new Employee("用户A:", 25000.0));
            e.Attach(new Employee("用户B:", 10000));
            e.Attach(new Employee("用户C:", "45000.0RMB"));

// Create two visitors
            DoubleVisitor v1 = new DoubleVisitor();
            Int32Visitor v2 = new Int32Visitor();
            StringVisitor v3 = new StringVisitor();
            // Employees are visited
            e.Accept(v1);
            e.Accept(v2);
            e.Accept(v3);

结构对象会遍历它自己所保存的聚集中的所有节点,在本系统中只有一个节点Employee。这个访问是由以下的操作组成的:

1. Employee对象的接受方法Accept被调用;

2. Employee对象反过来调用访问者对象的Visit方法,并将对象本身传入;

3. 访问者对象调用本身的Visit方法。

 访问者模式有如下的优点:

1. 访问者模式使得增加新的操作变得很容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。

2. 访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。

3. 访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。

4. 积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点。

访问者模式有如下的缺点:

1. 增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。

2. 破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。

注:

本文引用:《Java与模式》

http://www.cnblogs.com/zhenyulu/articles/79719.html

《大话设计模式》C#/C++版pdf/源码下载的更多相关文章

  1. HTML5与CSS3实例教程(第2版) 附源码 中文pdf扫描版

    HTML5和CSS3技术是目前整个网页的基础.<HTML5与CSS3实例教程(第2版)>共分3部分,集中讨论了HTML5和CSS3规范及其技术的使用方法.这一版全面讲解了最新的HTML5和 ...

  2. 跟我学SpringMVC目录汇总贴、PDF下载、源码下载

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  3. DRF终极封装ViewSet和Router附教程PDF源码

    在DRF官方教程的学习过程中,一个很明显的感受是框架在不断地进行封装,我们自己写框架/工具/脚本/平台也可以模仿模仿,先完成底层代码,再做多层封装,让使用者很容易就上手操作.本文是教程的最后一篇,介绍 ...

  4. PureMVC(JS版)源码解析:总结

    PureMVC源码中设计到的11个类已经全部解析完了,回首想想,花了一周的时间做的这点事情还是挺值得的,自己的文字组织表达能力和对pureMVC的理解也在写博客的过程中得到了些提升.我也是第一次写系列 ...

  5. PureMVC(JS版)源码解析

    PureMVC(JS版)源码解析:总结   PureMVC源码中设计到的11个类已经全部解析完了,回首想想,花了一周的时间做的这点事情还是挺值得的,自己的文字组织表达能力和对pureMVC的理解也在写 ...

  6. 【Python】《大话设计模式》Python版代码实现

    <大话设计模式>Python版代码实现 上一周把<大话设计模式>看完了,对面向对象技术有了新的理解,对于一个在C下写代码比较多.偶尔会用到一些脚本语言写脚本的人来说,很是开阔眼 ...

  7. 使用DevExpress的PdfViewer实现PDF打开、预览、另存为、打印(附源码下载)

    场景 Winform控件-DevExpress18下载安装注册以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1 ...

  8. 1-开发共享版APP(源码介绍)-BUG修复

    这一系列文章将介绍APP的源码,这一节作为所有BUG问题修复! https://www.cnblogs.com/yangfengwu/category/1512162.html    //开发共享版A ...

  9. 中秋礼物!开源即时通信GGTalk安卓版全新源码!

    经过连续两个多月的努力(开发.调试.测试.改bug),我们终于赶在中秋国庆之前能把全新的GGTalk Android版本献给大家. 4年之前我们就推出了GGTalk Android的第一个版本,但是功 ...

随机推荐

  1. [转]perf + 火焰图分析程序性能

    1.perf命令简要介绍 性能调优时,我们通常需要分析查找到程序百分比高的热点代码片段,这便需要使用 perf record 记录单个函数级别的统计信息,并使用 perf report 来显示统计结果 ...

  2. 安装odbc驱动

    1.下载对应的驱动 (32位/64位) http://www.oracle.com/technetwork/database/database-technologies/instant-client/ ...

  3. pip2和pip3冲突问题解决方法

    python使用pip安装模块时报错:unable to create process using ' '的解决方法: 参考:http://qoogle.cn/?id=39 1.删除C:\Python ...

  4. 6 个 Linux 运维典型问题,大牛的分析解决思路在这里 【转】

    作为一名合格的 Linux 运维工程师,一定要有一套清晰.明确的解决故障思路,当问题出现时,才能迅速定位.解决问题,这里给出一个处理问题的一般思路: 重视报错提示信息:每个错误的出现,都是给出错误提示 ...

  5. vector的reserve和resize(转)

    转自:http://www.cnblogs.com/qlee/archive/2011/05/16/2048026.html vector 的reserve增加了vector的capacity,但是它 ...

  6. javaweb笔记三

    //写了注解,就不用在web.xml里进行注册@WebServlet(urlPatterns="/my",name="my",loadOnStartup=1,i ...

  7. plaidctf-2016 Pwn试题小结

    回顾了一下今年plaidctf Pwn部分的题目,感觉还是蛮有意思的,值得研究一下. 1.unix_time_formatter-76 最简单的一道题,考点是UAF.说是UAF但是其实根本就不算是真正 ...

  8. 整理OpenResty+Mysql+Tomcat+JFinal+Cannal+HUI

    阿里云运维主机 118.190.89.22 26611 1.CentOS6.9下安装OpenResty 2.CentOS6.9下安装MariaDB10.2.11 3.使用Intellij IDEA把J ...

  9. mavean导入本地仓库

    当你刚开始用mavean的时候可能还没有发现mavean导入本地仓库方法的重要性,但是随着经常使用mavean项目就会发现,有些jar包mavean从网上的mavean仓库中无法导入,例如oracle ...

  10. Cname与A记录(Address)区别

    Cname与A记录(Address)区别A记录是解析域名到IP,Cname是解析域名到另外一个域名. 一台服务器可以布置多个网站,也可以有多个域名,如如域名A----->A记录-----> ...