Pergunta

Eu não sei se há um nome oficial para isso, mas eu tenho jogado com o que eu gosto de chamar o padrão de "auto-fábrica". Basicamente, é quando uma classe base abstrata atua como uma fábrica para si. Deixe-me explicar:

Eu tenho Foo objetos e Bar objetos no meu sistema, que são usados ??por meio de interfaces FooInterface e BarInterface. Eu preciso dar aos meus clientes o tipo certo de Foo e Bar. A decisão de qual objeto concreto Foo para criar é feita em tempo de compilação. Por exemplo, se você compilar em win32, você quer criar apenas Win32Foo objetos, e se você compilar em OSX você quiser criar apenas OSXFoo objetos e assim por diante. Mas, a decisão de qual objeto concreto Bar para criar é feita em tempo de execução, com base em uma seqüência chave.

Agora, a minha pergunta é sobre a melhor forma de implementar este regime. Uma maneira que eu vir para cima com usos fábricas regulares:

shared_ptr<FooInterface> foo = FooFactory::create();
shared_ptr<BarInterface> happyBar = BarFactory::create("Happy");
shared_ptr<BarInterface> sadBar = BarFactory::create("Sad");

Outra maneira é usar o que eu chamo de "auto-fábricas":

shared_ptr<FooInterface> foo = FooInterface::create();
shared_ptr<BarInterface> happyBar = BarInterface::create("Happy");
shared_ptr<BarInterface> sadBar = BarInterface::create("Sad");

Quais são os prós e contras de cada abordagem, tanto do ponto de vista da usabilidade e do ponto de vista arquitectónico?

Foi útil?

Solução

As fábricas têm dois usos comuns:

1) Decidir tipo polimórfico dinâmica em tempo de execução, com base nos parâmetros e / ou estado global (tal como a configuração). Seu padrão faz isso.

2) injeção de dependência: ao invés de usar uma função estática para criar objetos, use uma fábrica objeto , de modo que o tipo de objeto retornado pode ser configurado pelo chamador, passando em qualquer fábrica que quer. Nenhum desses padrões proporciona isso. Além disso, o seu segundo padrão nem sequer permitir a injeção de dependência estática (por ter funções de modelo que tomar uma classe de fábrica como um parâmetro do modelo), porque a interface ea fábrica são os mesmos.

Assim, um con do seu padrão (e de suas fábricas regulares) é que a injeção de dependência não é realmente suportados. Há uma e apenas uma função a ser chamada para obter um objeto que é uma FooInterface, e que é FooInterface :: create (). Eu não vou discutir por que a injeção de dependência é útil, basta salientar que se você construir desta forma, você não pode usá-lo.

Outras dicas

Eu faria uma melhoria:

shared_ptr<FooInterface> foo = Factory<FooInterface>::create();
shared_ptr<BarInterface> happyBar = Factory<BarInterface>::create("Happy");
shared_ptr<BarInterface> sadBar = Factory<BarInterface>::create("Sad");

Você iria declarar:

template <class I>
struct Factory { };

E, em seguida, para cada interface que precisa de uma fábrica, você faria o seguinte:

template <>
struct Factory<FooInterface>
{
    static FooInterface create();
};

Isto permite-lhe manter a implementação da fábrica separar a declaração interface, mas ainda utilizando o sistema de tipos para ligá-los em tempo de compilação.

Normalmente, as fábricas são responsáveis ??pela criação de objetos de hierarquias de classes inteiras. Assim, no seu exemplo, você teria um Win32Factory, OSXFactory etc. Uma vantagem disso é que você tem que selecionar a aplicação específica (win32 / unix / etc) apenas uma vez - durante a criação da fábrica, mas se você usar interfaces de classe, você tem para fornecer a informação oS todo o tempo.

Se você tem apenas duas classes (Foo e Bar) Eu não tenho certeza, se vale a pena o esforço para criar fábricas para eles e não apenas usar um método create das interfaces.

Oh, e quando uma interface tem um método para criar objetos de seu tipo, ele é chamado o método de fábrica padrão .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top