最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

聊聊C#中的Mixin的具體用法

 更新時間:2022年05月29日 09:31:45   作者:老胡寫代碼  
本文主要介紹了C#中的Mixin的具體用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

寫在前面

Mixin本意是指冰淇淋表面加的那些草莓醬,葡萄干等點(diǎn)綴物,它們負(fù)責(zé)給冰淇淋添加風(fēng)味。在OOP里面也有Mixin這個概念,和它的本意相似,OOP里面的Mixin意在為類提供一些額外功能——在不破壞類本身或者它的繼承鏈的基礎(chǔ)上,在某些情況下可能會起到妙用。今天跟著小編一起來看看吧。

從一個簡單例子說起

試想我們在寫一個游戲引擎,創(chuàng)建如下類:

    class ScriptManager
    {
        public void AddScript(){/*省略實(shí)現(xiàn)*/}

        public void RemoveScript(){/*省略實(shí)現(xiàn)*/}
    }

    class EntityManager
    {
        public void AddEntity() {/*省略實(shí)現(xiàn)*/}

        public void RemoveEntity() {/*省略實(shí)現(xiàn)*/}
    }

    class AnimationManager
    {
        public void AddAnimationToWorld() {/*省略實(shí)現(xiàn)*/}

        public void RemoveAnimationFromWorld() {/*省略實(shí)現(xiàn)*/}
    }

代碼非常簡單,三個manager類分別控制腳本、實(shí)體和動畫。但是我們突然發(fā)現(xiàn),這三個類應(yīng)該都是單例才合適。按照我們之前在C#中的Singleton中介紹的方法,我們這么改寫一下這三個類。

在類中實(shí)現(xiàn)單例

最簡單的,我們可以這么改

    class ScriptManager
    {
        private static ScriptManager _instance = null;
        public static ScriptManager Instance
        {
            get
            {
                if(_instance == null)
                {
                    lock(typeof(ScriptManager))
                    {
                        if(_instance == null)
                        {
                            _instance = new ScriptManager();
                        }
                    }
                }
                return _instance;
            }
        }
        public void AddScript(){/*省略實(shí)現(xiàn)*/}

        public void RemoveScript(){/*省略實(shí)現(xiàn)*/}
        private ScriptManager() {/*省略實(shí)現(xiàn)*/} //車門焊死,不讓外部調(diào)用
    }

	class EntityManager
	{
		//類似的修改方法
	}
	
	class AnimationManager
	{
		//類似的修改方法
	}

    static void Main(string[] args)
    {
        var instance1 = ScriptManager.Instance;
        var instance2 = ScriptManager.Instance;
        var result = instance1 == instance2; //true
    }

看起來沒有什么問題,確實(shí)也滿足了可用的要求,但是僅僅可用是不夠的,我們想要更好的解決方案,而且這種修改方法雖然簡單,但如果我們想要修改的類不止這三個,或者,我們想要添加的不僅僅是單例方法,我們需要寫的代碼會成倍增加,所以我們想要更好的解決方案。

在父類中實(shí)現(xiàn)單例

很容易就能想到,既然這塊代碼邏輯都是一樣的,我們?yōu)槭裁床话阉釤挼礁割??像這樣

    class SingletonHolder<T>
        where T : class
    {
        private static T _instance = null;
        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (typeof(T))
                    {
                        if (_instance == null)
                        {
                            _instance = (T)Activator.CreateInstance(typeof(T), true); //調(diào)用非公有構(gòu)造器
                        }
                    }
                }
                return _instance;
            }
        }
    }
    
    class ScriptManager : SingletonHolder<ScriptManager>
    {
		//省略
    }

    class EntityManager : SingletonHolder<EntityManager>
    {
		//省略
    }

    class AnimationManager : SingletonHolder<AnimationManager>
    {
		//省略
    }

    static void Main(string[] args)
    {
        var ScriptManager1 = ScriptManager.Instance;
        var ScriptManager2 = ScriptManager.Instance;
        var result = ScriptManager1 == ScriptManager2; //true

        var EntityManager1 = EntityManager.Instance;
        var EntityManager2 = EntityManager.Instance;
        result = EntityManager1 == EntityManager2; //true

        var AnimationManager1 = AnimationManager.Instance;
        var AnimationManager2 = AnimationManager.Instance;
        result = AnimationManager1 == AnimationManager2; //true
    }

確實(shí)可以,這樣就算有再多的類需要實(shí)現(xiàn)單例,只要讓它們繼承SingletonHolder就可以了,這樣的代碼方便擴(kuò)展也方便維護(hù),畢竟功能邏輯都在父類里面。

不過仔細(xì)想想,這樣的代碼還是有點(diǎn)問題,類繼承意味著子類應(yīng)該是父類的特化,代表著一種is-a的關(guān)系,但是我們這幾個Manager類和SingletonHolder并不是這種關(guān)系,它們和SingletonHolder更多像是一種實(shí)現(xiàn)契約的關(guān)系;如果一定要說is-a,它們應(yīng)該是引擎模塊(ModuleManager)的一種特化。所以讓它們繼承自SingletonHolder其實(shí)不是最好的方法,雖然語法正確、行為正確但是并不是語義正確,作為程序員,我們應(yīng)該追求盡善盡美。而且未來真有可能會抽象出一個父類ModuleManager,到時候就發(fā)現(xiàn)唯一的類繼承名額已經(jīng)給SingletonHolder給占用了,所以我們需要尋找一種既能注入邏輯代碼,又不涉及類繼承的方法。

輪到Mixin出場

定義

In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin's methods depends on the language. Mixins are sometimes described as being "included" rather than "inherited".
Mixins encourage code reuse and can be used to avoid the inheritance ambiguity that multiple inheritance can cause (the "diamond problem"), or to work around lack of support for multiple inheritance in a language. A mixin can also be viewed as an interface with implemented methods. This pattern is an example of enforcing the dependency inversion principle.

這是在Wiki上面Mixin的定義,允許程序員以在類繼承之外的方式為類添加一些方法,即,既能為類提供方法實(shí)現(xiàn),又可以避免成為類的父類,避免了類繼承和多重繼承所帶來的問題,這種概念正是我們需要的。

Mixin在C#中

在C#中,它們通常以擁有實(shí)現(xiàn)的接口出現(xiàn)(default implementation interface from C#8.0),而在C#8.0之前,我們通常以輔助類的方式來實(shí)現(xiàn)Mixin,我們下面以這兩種方式改寫之前的類。

在8.0之前

我們定義出一個接口,然后在外部基于這個接口實(shí)現(xiàn)單例邏輯(不用擴(kuò)展方法是因為擴(kuò)展方法不支持static method,如果想要注入的是非static method可以使用基于接口的擴(kuò)展方法)

    class SingletonHolder<T>
        where T : class, ISingleton
    {
        private static T _instance = null;
        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (typeof(T))
                    {
                        if (_instance == null)
                        {
                            _instance = (T)Activator.CreateInstance(typeof(T), true);
                        }
                    }
                }
                return _instance;
            }
        }
    }

    interface ISingleton
    {
        //沒有任何方法因為只是一個標(biāo)記
    }

    class ScriptManager : ISingleton
    {
        private ScriptManager() {/*省略實(shí)現(xiàn)*/}
        public void AddScript(){/*省略實(shí)現(xiàn)*/}

        public void RemoveScript(){/*省略實(shí)現(xiàn)*/}
    }

    class EntityManager : ISingleton
    {
        private EntityManager() {/*省略實(shí)現(xiàn)*/}
        public void AddEntity() {/*省略實(shí)現(xiàn)*/}

        public void RemoveEntity() {/*省略實(shí)現(xiàn)*/}
    }

    class AnimationManager : ISingleton
    {
        private AnimationManager() {/*省略實(shí)現(xiàn)*/}
        public void AddAnimationToWorld() {/*省略實(shí)現(xiàn)*/}

        public void RemoveAnimationFromWorld() {/*省略實(shí)現(xiàn)*/}
    }

    static void Main(string[] args)
    {
        var ScriptManager1 = SingletonHolder<ScriptManager>.Instance;
        var ScriptManager2 = SingletonHolder<ScriptManager>.Instance;
        var result = ScriptManager1 == ScriptManager2; //true

        var EntityManager1 = SingletonHolder<EntityManager>.Instance;
        var EntityManager2 = SingletonHolder<EntityManager>.Instance;
        result = EntityManager1 == EntityManager2; //true

        var AnimationManager1 = SingletonHolder<AnimationManager>.Instance;
        var AnimationManager2 = SingletonHolder<AnimationManager>.Instance;
        result = AnimationManager1 == AnimationManager2; //true
    }

這就是Mixin的用處,看起來這種實(shí)現(xiàn)方式的好處有:

  • 類只需要聲明實(shí)現(xiàn)ISingleton即可完成單例相關(guān)編碼
  • ISingleton是接口,類可以聲明實(shí)現(xiàn)多個接口而不會有類繼承的單一限制,同時也不會有那種is-a的類繼承煩惱
  • ISingleton是空接口,任何類實(shí)現(xiàn)它不需要額外的對該類自身的修改,就像淋上草莓醬不會對冰淇淋本身造成影響一樣,符合開閉原則

從C#8.0開始

從C#8.0開始,接口可以有方法的默認(rèn)實(shí)現(xiàn)(包括static method),我們可以更加簡單的實(shí)現(xiàn)Mixin解決之前的問題

    interface SingletonHolder<T>
        where T:class
    {
        private static T _instance = null;
        static T Instance
        {
            get
            {
                if(_instance == null)
                {
                    lock(typeof(T))
                    {
                        if(_instance == null)
                        {
                            _instance = (T)Activator.CreateInstance(typeof(T), true);
                        }
                    }
                }
                return _instance;
            }
        }
    }
    class ScriptManager : SingletonHolder<ScriptManager>{}
    class EntityManager : SingletonHolder<EntityManager>{}
    class AnimationManager : SingletonHolder<AnimationManager>{}

這就是Mixin以及它在C#中的簡單使用方法,希望通過這篇介紹能讓大家對這種用法有所了解,在想要給類添加代碼邏輯但是又不想改變類內(nèi)部或者影響類的繼承體系的時候,使用Mixin這種基于接口的代碼邏輯注入也許能有奇效哦。

到此這篇關(guān)于聊聊C#中的Mixin的具體用法的文章就介紹到這了,更多相關(guān)C# Mixin用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C# 數(shù)據(jù)驗證Regex示例詳解

    C# 數(shù)據(jù)驗證Regex示例詳解

    文章介紹了C#中使用Regex進(jìn)行數(shù)據(jù)驗證的方法,包括整數(shù)和小數(shù)的正負(fù)驗證,以及郵箱和身份證號的格式驗證,感興趣的朋友一起看看吧
    2025-02-02
  • Unity?數(shù)據(jù)存儲和讀取的方法匯總

    Unity?數(shù)據(jù)存儲和讀取的方法匯總

    這篇文章主要介紹了Unity?數(shù)據(jù)存儲和讀取的方法,本文通過四種方法在 Unity 中實(shí)現(xiàn)數(shù)據(jù)存儲和讀取方法的案例內(nèi)容,結(jié)合示例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • C# 時間與時間戳互轉(zhuǎn)的方法(13位)

    C# 時間與時間戳互轉(zhuǎn)的方法(13位)

    這篇文章主要介紹了C# 時間與時間戳互轉(zhuǎn)的方法(13位),詳細(xì)的介紹了常出現(xiàn)的幾種時間方式及其時間與時間戳互轉(zhuǎn)的方法,非常具有實(shí)用價值,希望此文章對各位有所幫助
    2018-10-10
  • C#中IEnumerable、ICollection、IList、List之間的區(qū)別

    C#中IEnumerable、ICollection、IList、List之間的區(qū)別

    這篇文章主要介紹了C#中IEnumerable、ICollection、IList、List之間的區(qū)別,本文分別分析了它的實(shí)現(xiàn)源碼,從而總結(jié)出了它們之間的關(guān)系和不同之處,需要的朋友可以參考下
    2015-06-06
  • C#實(shí)現(xiàn)公式計算驗證碼的示例詳解

    C#實(shí)現(xiàn)公式計算驗證碼的示例詳解

    現(xiàn)在很多的平臺已經(jīng)不使用普通的數(shù)字、字母等驗證碼了,取而代之的是拼圖類、選圖類、旋轉(zhuǎn)類或者計算類的驗證碼。本文將利用C#實(shí)現(xiàn)一個公式計算驗證碼,感興趣的可以了解一下
    2022-10-10
  • C#如何實(shí)現(xiàn)對sql server數(shù)據(jù)庫的增刪改查

    C#如何實(shí)現(xiàn)對sql server數(shù)據(jù)庫的增刪改查

    本文的主要內(nèi)容是C#實(shí)現(xiàn)對sql server數(shù)據(jù)庫的增刪改查,示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-08-08
  • Unity創(chuàng)建平鋪網(wǎng)格地圖的方法

    Unity創(chuàng)建平鋪網(wǎng)格地圖的方法

    這篇文章主要為大家詳細(xì)介紹了Unity創(chuàng)建平鋪網(wǎng)格地圖的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • C#繪制橢圓的方法

    C#繪制橢圓的方法

    這篇文章主要介紹了C#繪制橢圓的方法,涉及C#圖形繪制的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • C#實(shí)現(xiàn)的圖片、string相互轉(zhuǎn)換類分享

    C#實(shí)現(xiàn)的圖片、string相互轉(zhuǎn)換類分享

    這篇文章主要介紹了C#實(shí)現(xiàn)的圖片、string相互轉(zhuǎn)換類分享,本文直接給出類代碼,包含相互轉(zhuǎn)換的方法,需要的朋友可以參考下
    2015-03-03
  • C#使用 Salt + Hash 來為密碼加密

    C#使用 Salt + Hash 來為密碼加密

    本文主要介紹了幾種常見的破解密碼的方法,為密碼加鹽(Salt)以及在.NET中的實(shí)現(xiàn)等。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01

最新評論

应用必备| 朔州市| 霍林郭勒市| 霍山县| 邵阳市| 运城市| 乐安县| 留坝县| 独山县| 昭通市| 潜山县| 平和县| 临猗县| 抚州市| 柳河县| 长武县| 岑溪市| 开原市| 彝良县| 澳门| 霸州市| 乌拉特前旗| 松滋市| 滁州市| 苍梧县| 师宗县| 安宁市| 美姑县| 肇源县| 景泰县| 赣州市| 略阳县| 安龙县| 西充县| 棋牌| 抚州市| 寿阳县| 昌吉市| 五寨县| 博湖县| 广汉市|