zoukankan      html  css  js  c++  java
  • 23、访问者模式

    访问者模式:

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

    主要解决:稳定的数据结构和易变的操作耦合问题。
    如何解决:在被访问的类里面加一个对外提供接待访问者的接口。
    关键代码:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

    优点:1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。
    缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

    使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

    注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

    访问者模式UML结构图:

    从 UML类图中,我们可以看到,访问者模式主要包含五种角色:
    一、抽象访问者(Visitor):接口或抽象类,该类地冠以了对每一个具体元素(Element )的访 问行为visit()方法,其参数就是具体的元素(Element)对象。理论上来说,Visitor的方法个数与元素(Element )个数是相等的。如果元素(Element )个数经常变动,会导致Visitor的 方法也要进行变动,此时,该情形并不适用访问者模式;
    二、具体访问者(ConcreteVisitor):实现对具体元素的操作;
    三、抽象元素(Element ):接口或抽象类,定义了一个接受访问者访问的方法accept() , 表示所有元素类型都支持被访问者访问;
    四、具体元素(Concrete Element ):具体元素类型,提供接受访问者的具体实现。通常的实现都为 :visitor.visit(this);
    五、结构对象(ObjectStruture ):该类内部维护了元素集合,并提供方法接受访问者对该集合所有元素进行操作。

    基本代码:

     	abstract class Visitor
        {
            public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA);
    
            public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);
        }
    
        class ConcreteVisitor1 : Visitor
        {
            public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
            {
                Console.WriteLine("{0}被{1}访问", concreteElementA.GetType().Name, this.GetType().Name);
            }
    
            public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
            {
                Console.WriteLine("{0}被{1}访问", concreteElementB.GetType().Name, this.GetType().Name);
            }
        }
    
        class ConcreteVisitor2 : Visitor
        {
            public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
            {
                Console.WriteLine("{0}被{1}访问", concreteElementA.GetType().Name, this.GetType().Name);
            }
    
            public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
            {
                Console.WriteLine("{0}被{1}访问", concreteElementB.GetType().Name, this.GetType().Name);
            }
        }
    
        abstract class Element
        {
            public abstract void Accept(Visitor visitor);
        }
    
        class ConcreteElementA : Element
        {
            public override void Accept(Visitor visitor)
            {
                visitor.VisitConcreteElementA(this);
            }
    
            public void OperationA()
            { }
        }
    
        class ConcreteElementB : Element
        {
            public override void Accept(Visitor visitor)
            {
                visitor.VisitConcreteElementB(this);
            }
    
            public void OperationB()
            { }
        }
    
        class ObjectStructure
        {
            private IList<Element> elements = new List<Element>();
    
            public void Attach(Element element)
            {
                elements.Add(element);
            }
    
            public void Detach(Element element)
            {
                elements.Remove(element);
            }
    
            public void Accept(Visitor visitor)
            {
                foreach (Element e in elements)
                {
                    e.Accept(visitor);
                }
            }
        }
        
        class Program
        {
            static void Main(string[] args)
            {
                ObjectStructure o = new ObjectStructure();
                o.Attach(new ConcreteElementA());
                o.Attach(new ConcreteElementB());
    
                ConcreteVisitor1 v1 = new ConcreteVisitor1();
                ConcreteVisitor2 v2 = new ConcreteVisitor2();
    
                o.Accept(v1);
                o.Accept(v2);
    
                Console.Read();
            }
        }
    
  • 相关阅读:
    无法删除文件提示找不到指定文件导致文件无法删除的解决方法
    c++多线程编程(三)
    c++多线程编程(二)
    c++多线程编程(一)
    面试中的C++常见问题
    展示组件(Presentational component)和容器组件(Container component)之间有何不同
    如果你创建了类似于下面的 Twitter 元素,那么它相关的类定义是啥样子的?
    React 中 refs 的作用是什么?
    typescript 类(类的定义、继承、修饰符、抽象类)
    typescript 接口 interface
  • 原文地址:https://www.cnblogs.com/study-hard-forever/p/13167144.html
Copyright © 2011-2022 走看看