簡體   English   中英

限制類工廠設計模式

[英]Restricted class factory design pattern

有沒有一種優雅的(或任何)方式來實現C#的關注?

  • 讓我們擁有一個ItemBase類(進一步ItemBaseItem1Item2 ...),該類不允許直接實例化(非公共構造)-防止用戶創建Item*任何“未跟蹤”實例。
  • 我們有一個非靜態的類Manager ,其實例(允許多個實例) 只能創建和提供Item*實例(因為它們會跟蹤生成的實例並做一些額外的工作)。
  • 讓我們有一個可選的要求: Manager實例想操縱托管Item實例的非公共成員(類似於Manager成為Item*friend )。
  • 如果不強制Manager衍生Item*那將是很好的。
  • 如果反射越少越好。

筆記:

  • 如果可能的話,請考慮從如何以最佳,優雅的方式實施特定問題解決方案的過程中提出這個問題。 我希望它是通用的,不,我沒有資源,是的,我已經嘗試了一些變體,但是沒有一個能滿足我的需求。 謝謝。

  • 據我所知,沒有可以接受的friend替代方法( internalInternalsVisibleToAttribute都不錯),因此ItemBase僅提供了“特殊”(但公共)修改方法,用戶必須知道,這些方法不是為他:o(

  • 我喜歡這種解決方案 ,但是我無法發明如何允許多個Manager實例使用它。

我認為這可能會回答您的問題:

public class ItemBase

{
    protected ItemBase()
    {

    }
    public void PublicMethod() { }
    public int PublicProperty { get; set; }
}

public class Factory
{
    private class PrivateItemBase : ItemBase
    {
        public void PrivateMethod() { }
        public int PrivateProperty { get; set; }
    }

    public Factory(int id)
    {

    }

    public IEnumerable<ItemBase> Items { get; private set; }
    public ItemBase CreateItem()
    {
        PrivateItemBase rValue = new PrivateItemBase();

        rValue.PrivateMethod();
        rValue.PrivateProperty = 4;

        return rValue;
    }
}

好的,放棄。 如果這可以幫助您充分理解其目的,那么我(目前)最終會找到一種較差的解決方案。 傳遞創建函數是通過靜態構造函數(用戶無法訪問)完成的,不幸的是,丑陋的事情是它們的調用...

知道如何使它變得更好嗎?

項目定義:

namespace SpecialFactory
{
    public enum ItemType
    {
        Item1,
        Item2,
        // ... Anyone deriving the Item* should add an item here
    }

    public abstract class ItemBase
    {
        public abstract ItemType Id {get;}

        public static void RegisterAllCreators()
        {
            // Force static constructors invocation
            var it = Item1.ClassId | Item2.ClassId; // Anyone deriving the Item* should ensure invocation of Manager.RegisterCreator
        }
    }

    public class Item1 : ItemBase
    {
        static Item1()
        {
            Manager.RegisterCreator(ItemType.Item1, () => new Item1());
        }

        protected Item1()
        {
        }

        public static   ItemType ClassId => ItemType.Item1;
        public override ItemType Id      => ClassId;
    }

    public class Item2 : ItemBase
    {
        static Item2()
        {
            Manager.RegisterCreator(ItemType.Item2, () => new Item2());
        }

        protected Item2()
        {
        }

        public static   ItemType ClassId => ItemType.Item2;
        public override ItemType Id      => ClassId;
    }
}

管理者:

namespace SpecialFactory
{
    public class Manager
    {
        static Manager()
        {
            ItemBase.RegisterAllCreators();
        }

        protected static Dictionary<ItemType, Func<ItemBase>> creators = new Dictionary<ItemType, Func<ItemBase>>();
        protected readonly List<ItemBase> managedItems = new List<ItemBase>();

        protected ItemBase CreateItem(ItemType type)
        {
            ItemBase item = null;

            if (creators.ContainsKey(type))
            {
                if ((item = creators[type]()) != null)
                    managedItems.Add(item);
            }

            return item;    
        }

        public static void RegisterCreator(ItemType type, Func<ItemBase> creator)
        {
            if (!creators.ContainsKey(type))
                creators[type] = creator;
        }

        public Manager()
        {

        }

        public ItemBase Test(ItemType type)
        {
            // var notAllowed = new Item1();
            var allowed = CreateItem(type);

            return allowed;
        }
    }
}

考試:

namespace SpecialFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            var m1 = new Manager();
            var m2 = new Manager();

            var i1 = m1.Test(ItemType.Item1);
            var i2 = m2.Test(ItemType.Item2);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM