【问题标题】:How should I choose an instance of an AbstractFactory?我应该如何选择 AbstractFactory 的实例?
【发布时间】:2015-05-20 08:18:57
【问题描述】:

目前我在实例化 AbstractFactory 时遇到了麻烦。有一些类:

abstract class ABase { }
class A1 : ABase { }
class A2 : ABase { }

abstract class BBase { }
class B1 : BBase
{
    private readonly A1 _a;
    public B1(A1 a)
    {
        _a = a;
    }
}
class B2 : BBase
{
    private readonly A2 _a;
    public B2(A2 a)
    {
        _a = a;
    }
}


abstract class FactoryBBase
{
    abstract public BBase Create(ABase b);
}
class FactoryB1 : FactoryBBase
{
    override public BBase Create(ABase b)
    {
        return new B1(b as A1);
    }
}
class FactoryB2 : FactoryBBase
{
    override public BBase Create(ABase b)
    {
        return new B2(b as A2);
    }
}

class Runtime
{
    public void ProcessA(ABase a)
    {
        //How should I choose a proper factory?
    }
}

如何根据a 的类型在ProcessA 方法中实例化适当的抽象工厂?问题是我不想有一个大的 if/else 块。

【问题讨论】:

    标签: c# architecture abstract-factory


    【解决方案1】:

    如何根据 a 的类型在 ProcessA 方法中实例化适当的抽象工厂?

    为了避免大的 if/else 块,您可以将所有工厂放入一个映射中,其中 key 是 a 的类型,value 是实现。在 Java 中,我会通过 Spring 来执行此操作,或者我会创建一个静态代码,该代码可以在加载类时初始化映射。

    我应该使用 AbstractFactory 模式吗?

    恕我直言,是的。

    【讨论】:

    • 我目前的解决方案是这样的。我觉得没问题,但我希望有一个更优雅的解决方案。
    【解决方案2】:

    您可以使用查找字典而不是 if-else/switch 构造。

    //classes used as markers
    public interface IMarker {}
    public class MarkerA : IMarker {}
    public class MarkerB : IMarker {}
    
    //classes to be created
    public interface IData {}
    public class DataA : IData {}
    public class DataB : IData {}
    
    //factory to call abstract factories (could use static here)
    public class Factory
    {
        public IData Create(IMarker marker)
        {
            //lookup dictionary instead of if/switch
            //func ensures instance is only created when required
            var lookup = new Dictionary<Type, Func<DataFactoryBase>>()
            {
                { typeof(MarkerA), () => new DataAFactory() },
                { typeof(MarkerB), () => new DataBFactory() },
            };
    
            //get factory by type and call constructor
            return lookup[marker.GetType()]().Create();
        }
    }
    
    //abstract factories
    public abstract class DataFactoryBase
    {
        public abstract IData Create();
    }
    
    public class DataAFactory : DataFactoryBase
    {
        public override IData Create()
        {
            return new DataA();
        }
    }
    
    public class DataBFactory : DataFactoryBase
    {
        public override IData Create()
        {
            return new DataB();
        }
    }
    
    
    public static void Main()
    {
        //example will return DataA 
        IData data = new Factory().Create(new MarkerA());   
    }
    

    【讨论】:

    【解决方案3】:

    如何实现抽象工厂真的取决于你需要什么。你所拥有的确实是一个正确的实现,但我认为这并不完全是你所需要的,因为你想做一些不同的事情,具体取决于ABase 实例的类型或状态。

    分析类型或状态的逻辑正是我放入工厂的逻辑。

    abstract class ABase { }
    class A1 : ABase { }
    class A2 : ABase { }
    
    public abstract class FactoryBBase
    {
        public abstract IProcessor Create(ABase a);
    }
    public class ConcreteFactory : FactoryBBase
    {
        override public IProcessor Create(ABase a)
        {
            // this is ugly for a large amount of ABase implementations of course
            if (a is A1)
            {
                return new Runtime1();
            }
            if (a is A2)
            {
                return new Runtime2();
            }
            throw new NotSupportedException();
        }
    }
    
    public interface IProcessor
    {
        void ProcessA(ABase a);
    }
    
    public class Runtime1 : IProcessor
    {
        public void ProcessA(ABase a)
        {
            // process away
        }
    }
    
    public class Runtime2 : IProcessor
    {
        public void ProcessA(ABase a)
        {
            // process away differently
        }
    }
    

    当您希望 相同 类型的 ABase 实现由 不同 类型的 Runtime/Processor 处理时,多个工厂实现会发挥作用,具体取决于外部状态ABase.

    【讨论】:

    • 不完全是,我想对 BBase 的不同实例做同样的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    相关资源
    最近更新 更多