小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

C#設(shè)計(jì)模式學(xué)習(xí)筆記:(21)訪(fǎng)問(wèn)者模式

 頭號(hào)碼甲 2021-04-14

    本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/8135083.html,記錄一下學(xué)習(xí)過(guò)程以備后續(xù)查用。

    一、引言

    今天我們要講行為型設(shè)計(jì)模式的第九個(gè)模式--訪(fǎng)問(wèn)者模式。如果按老規(guī)矩,先從名稱(chēng)上來(lái)看這個(gè)模式,我根本不能獲得任何對(duì)理解該模式有用的信息,

而且這個(gè)模式在我們的編碼生活中使用的并不是很多。該模式的意圖定義很抽象,第一次看了這個(gè)定義其實(shí)和沒(méi)看沒(méi)有什么區(qū)別,一頭霧水。為了讓大家

更好的理解該模式的初衷,我們舉個(gè)例子來(lái)說(shuō)明模式。比如:當(dāng)客戶(hù)提出一個(gè)新的軟件需求的時(shí)候,大家經(jīng)過(guò)多個(gè)日以繼夜的努力,終于通過(guò)一個(gè)比較不

錯(cuò)的軟件設(shè)計(jì)解決了客戶(hù)的需求,而且這個(gè)設(shè)計(jì)有相對(duì)完美的類(lèi)層次結(jié)構(gòu)并且符合OO的設(shè)計(jì)原則,大家為此感到開(kāi)心,頗有成就感。又過(guò)了一段時(shí)間,

客戶(hù)突然又有一個(gè)新的需求,需要在現(xiàn)有的類(lèi)層次結(jié)構(gòu)里面增加一個(gè)新的操作(其實(shí)就是一個(gè)方法),怎么辦?還好,在面向OO設(shè)計(jì)模式中有一個(gè)模式

就是為了解決這個(gè)問(wèn)題的,那就是訪(fǎng)問(wèn)者模式,下面讓我們好好地了解一下該模式。

    二、訪(fǎng)問(wèn)者模式介紹

    訪(fǎng)問(wèn)者模式:英文名稱(chēng)--Visitor Pattern;分類(lèi)--行為型。

    2.1、動(dòng)機(jī)(Motivate)

    在軟件構(gòu)建過(guò)程中,由于需求的改變,某些類(lèi)層次結(jié)構(gòu)中常常需要增加新的行為(方法),如果直接在基類(lèi)中做這樣的更改,將會(huì)給子類(lèi)帶來(lái)很繁重的

變更負(fù)擔(dān),甚至破壞原有設(shè)計(jì)。如何在不更改類(lèi)層次結(jié)構(gòu)的前提下,在運(yùn)行時(shí)根據(jù)需要透明地為類(lèi)層次結(jié)構(gòu)上的各個(gè)類(lèi)動(dòng)態(tài)添加新的操作?

    2.2、意圖(Intent)

    表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各個(gè)元素的操作。它可以在不改變各元素的類(lèi)的前提下定義作用于這些元素的新的操作?!对O(shè)計(jì)模式》GoF

    2.3、結(jié)構(gòu)圖(Structure)

    2.4、模式的組成

    可以看出,在訪(fǎng)問(wèn)者模式的結(jié)構(gòu)圖有以下角色:

    1)抽象訪(fǎng)問(wèn)者角色(Visitor): 聲明一個(gè)包括多個(gè)訪(fǎng)問(wèn)操作,多個(gè)操作針對(duì)多個(gè)具體節(jié)點(diǎn)角色(可以說(shuō)有多少個(gè)具體節(jié)點(diǎn)角色就有多少訪(fǎng)問(wèn)操作),使

得所有具體訪(fǎng)問(wèn)者必須實(shí)現(xiàn)的接口。

    2)具體訪(fǎng)問(wèn)者角色(ConcreteVisitor):實(shí)現(xiàn)抽象訪(fǎng)問(wèn)者角色中所有聲明的接口,也可以說(shuō)是實(shí)現(xiàn)對(duì)每個(gè)具體節(jié)點(diǎn)角色的新的操作。

    3)抽象節(jié)點(diǎn)角色(Element):聲明一個(gè)接受操作,接受一個(gè)訪(fǎng)問(wèn)者對(duì)象作為參數(shù),如果有其它參數(shù),可以在這個(gè)“接受操作”里在定義相關(guān)的參數(shù)。

    4)具體節(jié)點(diǎn)角色(ConcreteElement):實(shí)現(xiàn)抽象元素所規(guī)定的接受操作。

    5)結(jié)構(gòu)對(duì)象角色(ObjectStructure):節(jié)點(diǎn)的容器,可以包含多個(gè)不同類(lèi)或接口的容器。

    2.5、訪(fǎng)問(wèn)者模式的具體實(shí)現(xiàn)

    訪(fǎng)問(wèn)者模式在我們現(xiàn)實(shí)的編碼生活中使用的并不是很多,我就直接貼代碼,讓大家看看代碼的結(jié)構(gòu)吧。今天給大家兩個(gè)代碼實(shí)例,實(shí)現(xiàn)代碼如下:

    class Program
    {
        /// <summary>
        /// 抽象圖形定義--相當(dāng)于“抽象節(jié)點(diǎn)角色”
        /// </summary>
        public abstract class Shape
        {
            //畫(huà)圖形
            public abstract void Draw();
            //外界注入具體訪(fǎng)問(wèn)者
            public abstract void Accept(ShapeVisitor visitor);
        }

        /// <summary>
        /// 矩形--相當(dāng)于“具體節(jié)點(diǎn)角色”
        /// </summary>
        public sealed class Rectangle : Shape
        {
            public override void Draw()
            {
                Console.WriteLine("矩形我已經(jīng)畫(huà)好了。");
            }

            public override void Accept(ShapeVisitor visitor)
            {
                visitor.Visit(this);
            }
        }

        /// <summary>
        /// 圓形--相當(dāng)于“具體節(jié)點(diǎn)角色”
        /// </summary>
        public sealed class Circle : Shape
        {
            public override void Draw()
            {
                Console.WriteLine("圓形我已經(jīng)畫(huà)好了。");
            }

            public override void Accept(ShapeVisitor visitor)
            {
                visitor.Visit(this);
            }
        }

        /// <summary>
        /// 直線(xiàn)--相當(dāng)于“具體節(jié)點(diǎn)角色”
        /// </summary>
        public sealed class Line : Shape
        {
            public override void Draw()
            {
                Console.WriteLine("直線(xiàn)我已經(jīng)畫(huà)好了。");
            }

            public override void Accept(ShapeVisitor visitor)
            {
                visitor.Visit(this);
            }
        }

        /// <summary>
        /// 抽象訪(fǎng)問(wèn)者
        /// </summary>
        public abstract class ShapeVisitor
        {
            public abstract void Visit(Rectangle shape);

            public abstract void Visit(Circle shape);

            public abstract void Visit(Line shape);

            //這里有一點(diǎn)要說(shuō):Visit方法的參數(shù)可以寫(xiě)成Shape嗎?就是這樣Visit(Shape shape)。
            //答案是可以,但是ShapeVisitor子類(lèi)的Visit方法就需要判斷當(dāng)前的Shape是什么類(lèi)型?是Rectangle類(lèi)型?還是Circle類(lèi)型?或者是Line類(lèi)型?
        }

        /// <summary>
        /// 具體訪(fǎng)問(wèn)者
        /// </summary>
        public sealed class CustomVisitor : ShapeVisitor
        {
            //針對(duì)Rectangle對(duì)象
            public override void Visit(Rectangle shape)
            {
                Console.WriteLine("針對(duì)Rectangle新的操作。");
            }
            //針對(duì)Circle對(duì)象
            public override void Visit(Circle shape)
            {
                Console.WriteLine("針對(duì)Circle新的操作。");
            }
            //針對(duì)Line對(duì)象
            public override void Visit(Line shape)
            {
                Console.WriteLine("針對(duì)Line新的操作。");
            }
        }

        /// <summary>
        /// 結(jié)構(gòu)對(duì)象角色
        /// </summary>
        internal class AppStructure
        {
            private readonly ShapeVisitor _visitor;

            public AppStructure(ShapeVisitor visitor)
            {
                _visitor = visitor;
            }

            public void Process(Shape shape)
            {
                shape.Accept(_visitor);
            }
        }

        static void Main(string[] args)
        {
            #region 訪(fǎng)問(wèn)者模式(第一個(gè)實(shí)例)
            ShapeVisitor visitor = new CustomVisitor();
            AppStructure app = new AppStructure(visitor);

            Shape shape = new Rectangle();
            shape.Draw();       //執(zhí)行自己的操作
            app.Process(shape); //執(zhí)行新的操作


            shape = new Circle();
            shape.Draw();       //執(zhí)行自己的操作
            app.Process(shape); //執(zhí)行新的操作


            shape = new Line();
            shape.Draw();       //執(zhí)行自己的操作
            app.Process(shape); //執(zhí)行新的操作

            Console.ReadLine();
            #endregion
        }
    }
View Code

    運(yùn)行結(jié)果如下:

    這是訪(fǎng)問(wèn)者模式第二個(gè)代碼實(shí)例:

    class Program
    {
        /// <summary>
        /// 抽象訪(fǎng)問(wèn)者角色
        /// </summary>
        public abstract class Visitor
        {
            public abstract void PutTelevision(Television tv);

            public abstract void PutComputer(Computer comp);
        }

        /// <summary>
        /// 具體訪(fǎng)問(wèn)者角色
        /// </summary>
        public sealed class SizeVisitor : Visitor
        {
            public override void PutTelevision(Television tv)
            {
                Console.WriteLine("按電視大小{0}排放。", tv.Size);
            }

            public override void PutComputer(Computer comp)
            {
                Console.WriteLine("按電腦大小{0}排放。", comp.Size);
            }
        }

        /// <summary>
        /// 具體訪(fǎng)問(wèn)者角色
        /// </summary>
        public sealed class StateVisitor : Visitor
        {
            public override void PutTelevision(Television tv)
            {
                Console.WriteLine("按電視新舊值{0}排放", tv.State);
            }

            public override void PutComputer(Computer comp)
            {
                Console.WriteLine("按電腦新舊值{0}排放", comp.State);
            }
        }

        /// <summary>
        /// 抽象節(jié)點(diǎn)角色
        /// </summary>
        public abstract class Goods
        {
            public abstract void Operate(Visitor visitor);
            public int Size { get; set; }
            public int State { get; set; }
        }

        /// <summary>
        /// 具體節(jié)點(diǎn)角色
        /// </summary>
        public sealed class Television : Goods
        {
            public override void Operate(Visitor visitor)
            {
                visitor.PutTelevision(this);
            }
        }

        /// <summary>
        /// 具體節(jié)點(diǎn)角色
        /// </summary>
        public sealed class Computer : Goods
        {
            public override void Operate(Visitor visitor)
            {
                visitor.PutComputer(this);
            }
        }

        /// <summary>
        /// 結(jié)構(gòu)對(duì)象角色
        /// </summary>
        public sealed class StoragePlatform
        {
            private IList<Goods> list = new List<Goods>();

            public void Attach(Goods element)
            {
                list.Add(element);
            }

            public void Detach(Goods element)
            {
                list.Remove(element);
            }

            public void Operate(Visitor visitor)
            {
                foreach (Goods g in list)
                {
                    g.Operate(visitor);
                }
            }
        }

        static void Main(string[] args)
        {
            #region 訪(fǎng)問(wèn)者模式(第二個(gè)實(shí)例)
            StoragePlatform platform = new StoragePlatform();
            platform.Attach(new Television());
            platform.Attach(new Computer());

            SizeVisitor sizeVisitor = new SizeVisitor();
            StateVisitor stateVisitor = new StateVisitor();

            platform.Operate(sizeVisitor);
            platform.Operate(stateVisitor);

            Console.Read();
            #endregion
        }
    }
View Code

    運(yùn)行結(jié)果如下:

    三、訪(fǎng)問(wèn)者模式的實(shí)現(xiàn)要點(diǎn)

    Visitor模式通過(guò)所謂雙重分發(fā)(double dispatch)來(lái)實(shí)現(xiàn)在不更改Element類(lèi)層次結(jié)構(gòu)的前提下,在運(yùn)行時(shí)透明地為類(lèi)層次結(jié)構(gòu)上的各個(gè)類(lèi)動(dòng)態(tài)添加新

的操作。所謂雙重分發(fā)即Visitor模式中間包括了兩個(gè)多態(tài)分發(fā)(注意其中的多態(tài)機(jī)制):第一個(gè)為accept方法的多態(tài)辨析;第二個(gè)為visit方法的多態(tài)辨析。

    設(shè)計(jì)模式其實(shí)是一種堵漏洞的方式,但是沒(méi)有一種設(shè)計(jì)模式能夠堵完所有的漏洞,即使是組合各種設(shè)計(jì)模式也是一樣。每個(gè)設(shè)計(jì)模式都有漏洞,都有

它們解決不了的情況或者變化。每一種設(shè)計(jì)模式都假定了某種變化,也假定了某種不變化。Visitor模式假定的就是操作變化,而Element類(lèi)層次結(jié)構(gòu)穩(wěn)定。

    3.1、訪(fǎng)問(wèn)者模式的主要優(yōu)點(diǎn)

    1)訪(fǎng)問(wèn)者模式使得添加新的操作變得容易。如果一些操作依賴(lài)于一個(gè)復(fù)雜的結(jié)構(gòu)對(duì)象的話(huà),那么一般而言,添加新的操作會(huì)變得很復(fù)雜。而使用訪(fǎng)問(wèn)

者模式,增加新的操作就意味著添加一個(gè)新的訪(fǎng)問(wèn)者類(lèi)。因此,使得添加新的操作變得容易。

    2)訪(fǎng)問(wèn)者模式使得有關(guān)的行為操作集中到一個(gè)訪(fǎng)問(wèn)者對(duì)象中,而不是分散到一個(gè)個(gè)的元素類(lèi)中。這點(diǎn)類(lèi)似與”中介者模式”。

    3)訪(fǎng)問(wèn)者模式可以訪(fǎng)問(wèn)屬于不同的等級(jí)結(jié)構(gòu)的成員對(duì)象,而迭代只能訪(fǎng)問(wèn)屬于同一個(gè)等級(jí)結(jié)構(gòu)的成員對(duì)象。

    3.2、訪(fǎng)問(wèn)者模式的主要缺點(diǎn)

    1)增加新的元素類(lèi)變得困難。每增加一個(gè)新的元素意味著要在抽象訪(fǎng)問(wèn)者角色中增加一個(gè)新的抽象操作,并在每一個(gè)具體訪(fǎng)問(wèn)者類(lèi)中添加相應(yīng)的具體

操作。具體來(lái)說(shuō),Visitor模式的最大缺點(diǎn)在于擴(kuò)展類(lèi)層次結(jié)構(gòu)(增添新的Element子類(lèi)),會(huì)導(dǎo)致Visitor類(lèi)的改變。因此Visitor模式適用于“Element類(lèi)層次

結(jié)構(gòu)穩(wěn)定,而其中的操作卻經(jīng)常面臨頻繁改動(dòng)”。

    3.3、在下面的情況下可以考慮使用訪(fǎng)問(wèn)者模式

    1)如果系統(tǒng)有比較穩(wěn)定的數(shù)據(jù)結(jié)構(gòu),而又有易于變化的算法時(shí),此時(shí)可以考慮使用訪(fǎng)問(wèn)者模式,因?yàn)樵L(fǎng)問(wèn)者模式使得算法操作的添加比較容易。

    2)如果一組類(lèi)中,存在著相似的操作,為了避免出現(xiàn)大量重復(fù)的代碼,可以考慮把重復(fù)的操作封裝到訪(fǎng)問(wèn)者中(當(dāng)然也可以考慮使用抽象類(lèi)了)。

    3)如果一個(gè)對(duì)象存在著一些與本身對(duì)象不相干或關(guān)系比較弱的操作時(shí),為了避免操作污染這個(gè)對(duì)象,則可以考慮把這些操作封裝到訪(fǎng)問(wèn)者對(duì)象中。

    四、.NET中訪(fǎng)問(wèn)者模式的實(shí)現(xiàn)

    在現(xiàn)在的.Net框架里面,如果要想給現(xiàn)有的類(lèi)增加新的方法,有了新的方式,那就是“擴(kuò)展方法”,使用起來(lái)和實(shí)例方法是一樣一樣的,而且在.Net

框架里面,微軟自己也寫(xiě)了很多的擴(kuò)展方法給我們使用。我目前還沒(méi)有學(xué)習(xí)到.Net的框架類(lèi)庫(kù)里面有“訪(fǎng)問(wèn)者模式”實(shí)現(xiàn),看來(lái)自己還需努力,革命尚

未成功啊。

    五、總結(jié)

    訪(fǎng)問(wèn)者模式寫(xiě)完了,這個(gè)模式剛開(kāi)始理解起來(lái)還是挺麻煩的,但是,如果我們多看幾個(gè)實(shí)例代碼,完全掌握也不是問(wèn)題。隨著C#語(yǔ)言的發(fā)展,設(shè)

計(jì)模式里面的很多東西,我們可以通過(guò)C#語(yǔ)言的一些特性做更好的替代。我們寫(xiě)設(shè)計(jì)模式剛開(kāi)始要慢慢來(lái),一步一步照貓畫(huà)虎地來(lái)寫(xiě)代碼,等我們

熟練掌握了模式的核心思想,我們就要寫(xiě)符合C#風(fēng)格和特性的模式代碼了,或者說(shuō)我們要用C#來(lái)寫(xiě)設(shè)計(jì)模式了,寫(xiě)出來(lái)的代碼也會(huì)更棒。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多