访问者模式

目录

一、访问者模式

二、访问者模式角色

三、代码实例一

四、代码实例二

五、代码实例三 

UML图


一、访问者模式

访问者模式表示一个作用于某对象结构中的各元素操作。它使你在不改变各元素的类的前提下定义作用于这些元素的操作

增加状态比较简单,符合开闭原则,但是增加元素困难,不符合开闭原则。类似于抽象工厂,以一种倾斜的方式扩展(方法集合的可扩展和类集合的不可扩展)。

本质是预留通路,回调实现。

当操作需要更改时,将更新封装到一个类中,并由等待更改类提供一个接口。

需要注意:

1、访问者模式适用于数据结构稳定,而操作可以不稳定。将操作和数据结构解耦。

2、数据结构每一个节点都可以接受一个访问的调用,这个节点将自己传入访问者,访问者执行节点对象的操作--双重分派

3、操作基于数据结构和访问者的数据类型。

4、有一个非常重要的结构类,结构对象会保存一系列节点类,下文中 节点类调用自己的ACCEPT函数,将VISITOR传入,然后VISITOR对象执行操作。

pros and cons

pros:

1、增加新的操作非常容易,即增加一个访问者类

2、将有关行为集中到一个访问者对象中,而不是节点中。

cons:

1、增加新的节点十分困难。若增加新节点,就要在抽象访问者中增加一个新操作。不符合开闭原则。

2、破坏了封装,访问者对象要访问并调用节点对象的操作。节点类必须暴露自己的一些操作和内部状态。

二、访问者模式角色

1、抽象元素类

元素类结构稳定,就像下面的例子,人有男女之分,结构稳定。

2、具体元素类,就像男人女人类。

3、抽象访问者类

有抽象函数,并且参数是抽象元素类,便于回调。

4、具体类

实现抽象状态类中抽象方法。

5、结构类

集中处理,迭代遍历。

三、代码实例一

访问者类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    abstract class Action
    {
        public abstract void ManAction( Man man);
        public abstract void WomanAction(Woman woman);
    }
}

具体访问者类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    class Love : Action
    {
        public override void ManAction(Man man)
        {
            Console.WriteLine(man.GetType().Name + "  恋爱  " + this.GetType().Name);
        }

        public override void WomanAction(Woman woman)
        {
            Console.WriteLine(woman.GetType().Name + "  恋爱  " + this.GetType().Name);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    class Fail : Action
    {
        public override void ManAction(Man man)
        {
            Console.WriteLine(man.GetType().Name + "  失败  " + this.GetType().Name);
        }

        public override void WomanAction(Woman woman)
        {
            Console.WriteLine(woman.GetType().Name + "  失败  " + this.GetType().Name);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    class Success : Action
    {
        public override void ManAction(Man man)
        {
            Console.WriteLine(man.GetType().Name + "  成功  " + this.GetType().Name);
        }

        public override void WomanAction(Woman woman)
        {
            Console.WriteLine(woman.GetType().Name + "  成功  " + this.GetType().Name);
        }
    }
}

元素类,有一个Accept函数,参数为状态类型。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    abstract class Person
    {
        public abstract void Accept(Action visitor); 
    }
}

一般元素类的子类是固定的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    class Man : Person
    {
        public override void Accept(Action visitor)
        {
            visitor.ManAction(this);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    class Woman : Person
    {
        public override void Accept(Action visitor)
        {
            visitor.WomanAction(this);
        }
    }
}

结构类,便于批处理

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    class Structure
    {
        private List<Person> lists = new List<Person>();
        public void Attach(Person person)
        {
            lists.Add(person);
        }
        public void Detach(Person person)
        {
            lists.Remove(person);
        }
        public void Run(Action visitor)
        {
            foreach (Person person in lists)
            {
                person.Accept(visitor);
            }
        }

    }
}

测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace VisitorOne
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Structure structure = new Structure();
            structure.Attach(new Man());
            structure.Attach(new Woman());
            Success success = new Success();
            structure.Run(success);
            structure.Run(new Love());
            structure.Run(new Fail());

        }
    }
}

如果想再增加一个失恋状态,只需要让他增加一个失恋类,继承行为类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorOne
{
    class UnLove : Action
    {
        public override void ManAction(Man man)
        {
            Console.WriteLine(man.GetType().Name + "  失恋  " + this.GetType().Name);
        }

        public override void WomanAction(Woman woman)
        {
            Console.WriteLine(woman.GetType().Name + "  失恋  " + this.GetType().Name);
        }
    }
}

 

四、代码实例二

实现账单的访问。

访问者类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Visitor_Bill
{
    abstract class AccountView
    {
        public abstract void InView(InAccount account);
        public abstract void OutView(OutAccount account);
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Visitor_Bill
{
    class Boss : AccountView
    {
        public override void InView(InAccount account)
        {
            Console.WriteLine(this.GetType().Name + "  " + account.GetType().Name);
        }

        public override void OutView(OutAccount account)
        {
            Console.WriteLine(this.GetType().Name + "  " + account.GetType().Name);
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Visitor_Bill
{
    class Secretary : AccountView
    {
        public override void InView(InAccount account)
        {
            Console.WriteLine(this.GetType().Name + "  " + account.GetType().Name);
        }

        public override void OutView(OutAccount account)
        {
            Console.WriteLine(this.GetType().Name + "  " + account.GetType().Name);
        }
    }
}

元素类,元素类为账单,只包含支出和收入,结构稳定

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Visitor_Bill
{
    abstract class Account
    {
        public abstract void View(AccountView visitor_AccountView);
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Visitor_Bill
{
    class InAccount : Account
    {
        public override void View(AccountView visitor_AccountView)
        {
            visitor_AccountView.InView(this);
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Visitor_Bill
{
    class OutAccount : Account
    {
        public override void View(AccountView visitor_AccountView)
        {
            visitor_AccountView.OutView(this);
        }
    }
}

 结构类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Visitor_Bill
{
    class Structure
    {
        private List<Account> lists = new List<Account>();
        public void Attach(Account account)
        {
            lists.Add(account);
        }
        public void Detach(Account account)
        {
            lists.Remove(account);
        }
        public void Viewing(AccountView accountView)
        {
            foreach (Account account in lists)
            {
                account.View(accountView);
            }
        }
    }
}

测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Visitor_Bill
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Structure structure = new Structure();
            structure.Attach(new InAccount());
            structure.Attach(new OutAccount());
            structure.Viewing(new Boss());
            structure.Viewing(new Secretary());
        }
    }
}

五、代码实例三 

扩展客户管理的功能(CRM)。 (节点)个人客户、企业客户。 (访问者)提出服务申请、客户价值分析、客户对产品偏好分析等。

访问者

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorCRM
{
    abstract class Visitor
    {
        public abstract void VisitCompany(Company company);
        public abstract void VisitPersonal(Personal personal);
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorCRM
{
    class Request : Visitor
    {
        public override void VisitCompany(Company company)
        {
            Console.WriteLine(company.GetType().Name+" "+this.GetType().Name);
        }

        public override void VisitPersonal(Personal personal)
        {
            Console.WriteLine(personal.GetType().Name + " " + this.GetType().Name);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorCRM
{
    class Analyse : Visitor
    {
        public override void VisitCompany(Company company)
        {
            Console.WriteLine(company.GetType().Name + " " + this.GetType().Name);
        }

        public override void VisitPersonal(Personal personal)
        {
            Console.WriteLine(personal.GetType().Name + " " + this.GetType().Name);
        }
    }
}

节点类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorCRM
{
    abstract class Element
    {
        public abstract void Accept(Visitor visitor);
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorCRM
{
    class Personal : Element
    {
        public override void Accept(Visitor visitor)
        {
            visitor.VisitPersonal(this);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisitorCRM
{
    class Company : Element
    {
        public override void Accept(Visitor visitor)
        {
            visitor.VisitCompany(this);
        }
    }
}

 测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace VisitorCRM
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Request request = new Request();
            Analyse analyse = new Analyse();
            request.VisitCompany(new Company());
            analyse.VisitCompany(new Company());
        }
    }
}

UML图

c#生成的不咋好看啊

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值