2015-05-20 3 views
2

В настоящее время у меня возникли проблемы с созданием AbstractFactory.
Есть несколько классов:Как выбрать экземпляр 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? 
    } 
} 

Вопрос в том, как создать экземпляр надлежащего абстрактную фабрику в ProcessA метода в зависимости от типа a? Дело в том, что я не хочу иметь большой блок if/else.
Другой вопрос: использовать шаблон AbstractFactory, поскольку он должен быть uesd?

ответ

1

Как создать экземпляр надлежащей абстрактной фабрики в методе ProcessA в зависимости от типа?

Чтобы избежать большого блока if/else, вы можете поместить все заводы в карту, где ключ - это тип a, а значение - это реализация. в Java я бы сделал это либо Spring, либо создаю статический код, который может инициализировать карту при загрузке класса.

Я использую шаблон AbstractFactory, поскольку он должен быть uesd?

ИМХО да.

+0

Мое текущее решение - это что-то вроде этого. Я нахожу это в порядке, но я надеюсь, что есть более элегантное решение. – dmigo

1

Как реализовать абстрактный завод действительно зависит от того, что вам нужно. То, что у вас есть, действительно является правильной реализацией, но я думаю, что это не совсем то, что вам нужно, так как вы хотите сделать что-то по-другому, зависящее от типа или состояния экземпляра 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 реализации же быть обработаны различными типов времени выполнения/процессора в зависимости от состояния, которая находится вне ABase.

+0

Не совсем, я хотел бы сделать то же самое с разными экземплярами 'BBase'. – dmigo

1

Вы можете использовать словарь поиска вместо конструкции 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()); 
} 
+0

Меня беспокоит то, что 'Factory' знает обо всех возможных реализациях. Они могут находиться в разных пространствах имен/проектах/dll, а 'Factory' должен ссылаться на все. Это может быть проблемой в моем случае. – dmigo

+0

Попробуйте использовать инъекцию зависимостей, например. Ninject. https://github.com/ninject/ninject.extensions.factory/wiki – Greg

+0

Я использую Unity, но я не знаю, как применить его для решения проблемы. – dmigo

Смежные вопросы