受限制的类工厂设计模式

时间:2015-09-11 14:03:03

标签: c# friend class-factory

是否有优雅(或任何)方式在C#中实现以下内容?

  • 让我们有一个类ItemBase(进一步派生到Item1Item2 ...),它不允许直接实例化(非公开构建) - 阻止用户创建任何未跟踪的' Item*的实例。
  • 我们有一个非静态类Manager,其实例(允许多个)可以创建并提供Item*的实例(因为它们保留跟踪生成的实例并做一些额外的工作)。
  • 我们有一个可选的要求:Manager个实例想要操纵托管Item个实例的非公开成员(类似于Manager将是{ {1}} {1}}。{/ li>
  • 如果friend不被强制推导出Item*,那就太好了。
  • 如果尽可能少的反思会很好。

注意:

  • 如果可能,请将此视为从最佳和优雅的方式思考如何实施特定问题解决方案的过程中提出的问题。我希望它是一般的,不,我没有消息来源,是的,我已经尝试了一些变体,但它们都没有满足我的需求。谢谢。

  • 据我所知,没有可接受的Manager替代方案(任何Item*friend似乎都很好),所以{{1只提供特殊的' (但是公开的)修改方法和用户必须知道,这些方法不适合他:o(

  • 我喜欢this solution,但我无法发明,如何允许多个internal实例使用它。

    < / LI>

2 个答案:

答案 0 :(得分:0)

我认为这可能会解决您的问题:

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;
    }
}

答案 1 :(得分:0)

好的,放弃。如果这可能有助于完全理解目的,那么我(目前)最终解决的问题就不那么糟糕了。传递创建函数是通过静态构造函数(用户无法访问)完成的,不幸的是丑陋的是他们的调用......

知道如何让它变得更好吗?

项目定义:

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);
        }
    }
}