天天看點

通路者模式

《大話設計模式》閱讀筆記和總結。原書是C#編寫的,本人用Java實作了一遍,包括每種設計模式的UML圖實作和示例代碼實作。

目錄:

設計模式 Github位址: DesignPattern

說明

定義:通路者模式(Visitor),表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。

UML圖:

通路者模式

通路者模式UML圖.png

代碼實作:

Visitor類,為該對象結構中ConcreteElement的每一個類聲明一個Visit操作

abstract class Visitor{
    public abstract void VisitConcreteElementA(ConcreteElementA elementA);
    public abstract void VisitConcreteElementB(ConcreteElementB elementB);
}
           

ConcreteVisitor1和ConcreteVisitor2類,具體通路者,實作每個由Visitor聲明的操作。每個操作實作算法的一部分,而該算法片段是對應于結構中對象的類

class ConcreteVisitor1 extends Visitor {

    @Override
    public void VisitConcreteElementA(ConcreteElementA concreteElementA) {
        System.out.println(concreteElementA.getClass().getSimpleName() + "被"
                + this.getClass().getSimpleName() + "通路");
    }

    @Override
    public void VisitConcreteElementB(ConcreteElementB concreteElementB) {
        System.out.println(concreteElementB.getClass().getSimpleName() + "被"
                + this.getClass().getSimpleName() + "通路");
    }

}

class ConcreteVisitor2 extends Visitor {

    @Override
    public void VisitConcreteElementA(ConcreteElementA concreteElementA) {
        System.out.println(concreteElementA.getClass().getSimpleName() + "被"
                + this.getClass().getSimpleName() + "通路");
    }

    @Override
    public void VisitConcreteElementB(ConcreteElementB concreteElementB) {
        System.out.println(concreteElementB.getClass().getSimpleName() + "被"
                + this.getClass().getSimpleName() + "通路");
    }

}
           

Element類,定義一個Accept操作,它以一個通路者為參數

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

ConcreteElementA和ConcreteElementB類,具體元素,實作Accept操作

class ConcreteElementA extends Element{

    @Override
    public void Accept(Visitor visitor) {
        visitor.VisitConcreteElementA(this);
    }

    public void OperationA(){

    }
}

class ConcreteElementB extends Element{

    @Override
    public void Accept(Visitor visitor) {
        visitor.VisitConcreteElementB(this);
    }

    public void OperationB(){

    }
}

           

ObjectStructure類,能枚舉它的元素,可以提供一個高層的接口以允許通路者通路它的元素

class ObjectStructure{
    private List<Element> elements = new ArrayList<>();
    public void Attach(Element element){
        elements.add(element);
    }
    public void Detach(Element element){
        elements.remove(element);
    }
    public void Accept(Visitor visitor){
        for (Element e :elements) {
            e.Accept(visitor);
        }
    }
}
           

用戶端代碼

public class VisitorPattern {
    public 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);
    }
}
           

運作結果

ConcreteElementA被ConcreteVisitor1通路
ConcreteElementB被ConcreteVisitor1通路
ConcreteElementA被ConcreteVisitor2通路
ConcreteElementB被ConcreteVisitor2通路
           

示例

例子:程式要求實作當男人和女人在不同狀态下的反應。

男人成功時,背後多半有一個偉大的女人。

女人成功時,背後多半有一個偉大的男人。

男人失敗時,悶頭喝酒,誰也不用勸。

女人失敗時,眼淚汪汪,誰也勸不了。

男人戀愛時,凡是不懂也要裝懂。

女人戀愛時,遇事懂也裝作不懂。

男女對比這麼多的原因就是因為人類在性别上就隻有男人和女人兩類。

通路者模式

通路者模式示例UML圖.png

抽象元素

public abstract class Person {
    public abstract void Accept(Action action);
}
           

男人

public class Man extends Person{

    @Override
    public void Accept(Action action) {
        action.GetManConclusion(this);
    }

}
           

女人

public class Woman extends Person{

    @Override
    public void Accept(Action action) {
        action.GetWomanConclusion(this);
    }

}
           

抽象狀态類

public abstract class Action {
    public abstract void GetManConclusion(Person man);

    public abstract void GetWomanConclusion(Person woman);

}
           

成功狀态

public class Success extends Action{

    @Override
    public void GetManConclusion(Person man) {
        System.out.println("男人成功時");
    }

    @Override
    public void GetWomanConclusion(Person woman) {
        System.out.println("女人成功時");
    }

}
           

失敗狀态

public class Failing extends Action{

    @Override
    public void GetManConclusion(Person man) {
        System.out.println("男人失敗時");
    }

    @Override
    public void GetWomanConclusion(Person woman) {
        System.out.println("女人失敗時");
    }

}
           

戀愛狀态

public class Amativeness extends Action {

    @Override
    public void GetManConclusion(Person man) {
        System.out.println("男人戀愛時");
    }

    @Override
    public void GetWomanConclusion(Person woman) {
        System.out.println("女人戀愛時");
    }

}
           

結婚狀态

public class Marriage extends Action{

    @Override
    public void GetManConclusion(Person man) {
        System.out.println("男人結婚時...");

    }

    @Override
    public void GetWomanConclusion(Person woman) {
        System.out.println("女人結婚時...");
    }

}
           

對象結構,用于通路男,女元素

public class PersonObjectStructure {
    //對象結構,用于通路男,女元素
    private List<Person> list = new ArrayList<>();

    public void Attach(Person person) {
        list.add(person);
    }

    public void Detach(Person person) {
        list.remove(person);
    }

    public void Display(Action action) {
        for (Person person : list) {
            person.Accept(action);
        }
    }

}
           
public class Main {
    public static void main(String[] args) {
        PersonObjectStructure objectStructure=new PersonObjectStructure();
        objectStructure.Attach(new Man());
        objectStructure.Attach(new Woman());

        //看男人和女人在成功時的狀态
        Success success=new Success();
        objectStructure.Display(success);

        //新增一個結婚狀态
        Marriage marriage=new Marriage();
        objectStructure.Display(marriage);
    }
}

           
男人成功時
女人成功時
男人結婚時...
女人結婚時...
           

繼續閱讀