天天看點

設計模式---通路者模式(DesignPattern_Visitor)

摘錄自:設計模式與遊戲完美開發
十年磨一劍,作者将設計模式理論巧妙地融入到實踐中,以一個遊戲的完整實作呈現設計模式的應用及經驗的傳承 《軒轅劍》之父——蔡明宏、資深遊戲制作人——李佳澤、Product Evangelist at Unity Technologies——Kelvin Lo、信仁軟體設計創辦人—— 賴信仁、資深3D遊戲美術——劉明恺 聯合推薦全書采用了整合式的項目教學,即以一個遊戲的範例來應用23種設計模式的實作貫穿全書,讓讀者學習到整個遊戲開發的全過程和作者想要傳承的經驗,并以淺顯易懂的比喻來解析難以了解的設計模式,讓想深入了解此領域的讀者更加容易上手。

工程GitHub

VISITOR—情人節到了,要給每個MM送一束鮮花和一張卡片,可是每個MM送的花都要針對她個人的特點,每張卡片也要根據個人的特點來挑,我一個人哪搞得清楚,還是找花店老闆和禮品店老闆做一下Visitor,讓花店老闆根據MM的特點選一束花,讓禮品店老闆也根據每個人特點選一張卡,這樣就輕松多了;

通路者模式:通路者模式的目的是封裝一些施加于某種資料結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的資料結構可以保持不變。通路者模式适用于資料結構相對未定的系統,它把資料結構和作用于結構上的操作之間的耦合解脫開,使得操作集合可以相對自由的演化。通路者模式使得增加新的操作變的很容易,就是增加一個新的通路者類。通路者模式将有關的行為集中到一個通路者對象中,而不是分散到一個個的節點類中。當使用通路者模式時,要将盡可能多的對象浏覽邏輯放在通路者類中,而不是放到它的子類中。通路者模式可以跨過幾個類的等級結構通路屬于不同的等級結構的成員類。

using UnityEngine;
using System.Collections.Generic;

namespace DesignPattern_Visitor
{   
    // 固定的元素, 定義給Visitor存取的介面
    public abstract class Visitor
    {   
        // 可以寫一個通用的函數名稱但以用不同的參數來産生多樣化方法
        public abstract void VisitConcreteElement( ConcreteElementA theElement);
        public abstract void VisitConcreteElement( ConcreteElementB theElement);


        // 或可以針對Element的子類做不同的執行操作
        public abstract void VisitConcreteElementA( ConcreteElementA theElement);
        public abstract void VisitConcreteElementB( ConcreteElementB theElement);

    }

    // 制定以Visitor物件當參數的Accept()介面
    public abstract class Element
    {   
        public abstract void Accept( Visitor theVisitor);       
    }

    // 元素A 
    public class ConcreteElementA : Element
    {
        public override void Accept( Visitor theVisitor)
        {
            theVisitor.VisitConcreteElement( this );
            theVisitor.VisitConcreteElementA( this );
        }

        public void OperationA()
        {
            Debug.Log("ConcreteElementA.OperationA");
        }
    }
    
    // 元素B
    public class ConcreteElementB : Element
    {
        public override void Accept( Visitor theVisitor)
        {
            theVisitor.VisitConcreteElement( this );
            theVisitor.VisitConcreteElementB( this );
        }

        public void OperationB()
        {
            Debug.Log("ConcreteElementB.OperationB");
        }
    }
    
    // 執行個體功能操作Visitor1
    public class ConcreteVicitor1 : Visitor
    {
        // 可以寫一個通用的函數名稱但以用不同的參數來産生多樣化方法
        public override void VisitConcreteElement( ConcreteElementA theElement)
        {
            Debug.Log ("ConcreteVicitor1:VisitConcreteElement(A)");
        }
        public override void VisitConcreteElement( ConcreteElementB theElement)
        {
            Debug.Log ("ConcreteVicitor1:VisitConcreteElement(B)");
        }

        public override void VisitConcreteElementA( ConcreteElementA theElement)
        {
            Debug.Log ("ConcreteVicitor1.VisitConcreteElementA()");
            theElement.OperationA();
        }

        public override void VisitConcreteElementB( ConcreteElementB theElement)
        {
            Debug.Log ("ConcreteVicitor1.VisitConcreteElementB()");
            theElement.OperationB();
        }
    }

    // 執行個體功能操作Visitor2
    public class ConcreteVicitor2 : Visitor
    {
        // 可以寫一個通用的函數名稱但以用不同的參數來産生多樣化方法
        public override void VisitConcreteElement( ConcreteElementA theElement)
        {
            Debug.Log ("ConcreteVicitor2:VisitConcreteElement(A)");
        }
        public override void VisitConcreteElement( ConcreteElementB theElement)
        {
            Debug.Log ("ConcreteVicitor2.VisitConcreteElement(B)");
        }

        public override void VisitConcreteElementA( ConcreteElementA theElement)
        {
            Debug.Log ("ConcreteVicitor2.VisitConcreteElementA()");
            theElement.OperationA();
        }
        
        public override void VisitConcreteElementB( ConcreteElementB theElement)
        {
            Debug.Log ("ConcreteVicitor2.VisitConcreteElementB()");
            theElement.OperationB();
        }   
    }
        
    // 用來儲存所有的Element   
    public class ObjectStructure
    {
        List<Element> m_Context = new List<Element>();
    
        public  ObjectStructure()
        {
            m_Context.Add( new ConcreteElementA());
            m_Context.Add( new ConcreteElementB());
        }
        
        // 載入不同的Action(Visitor)來判斷
        public void RunVisitor(Visitor theVisitor)
        {
            foreach(Element theElement in m_Context )
                theElement.Accept( theVisitor);
        }
    }
    
}
           
using UnityEngine;
using System.Collections;
using DesignPattern_Visitor;

public class VisitorTest : MonoBehaviour
{

    void Start()
    {
        UnitTest();
    }

   
    void UnitTest()
    {
        ObjectStructure theStructure = new ObjectStructure();

        // 將Vicitor周遊ObjectStructure裡面各元表
        theStructure.RunVisitor(new ConcreteVicitor1());
        theStructure.RunVisitor(new ConcreteVicitor2());
    }
}
           

繼續閱讀