Motivação
- Nos sistemas de software, geralmente enfrentamos a tarefa de criar objetos; devido a mudanças nos requisitos, os tipos específicos de objetos que precisam ser criados frequentemente mudam.
- Como lidar com essa mudança? Como ignorar o método convencional de criação de objetos (novo) e fornecer um "mecanismo de encapsulamento" para evitar o forte acoplamento entre o programa cliente e esse "trabalho concreto de criação de objetos"?
Definição de padrão
Defina uma interface para criar objetos e deixe as subclasses decidirem qual classe instanciar. O Método de Fábrica atrasa a instanciação de uma classe (finalidade: dissociação, significa: função virtual) para subclasses. - GoF "Modo Design"
Exemplos de padrões
O exemplo do divisor de arquivo foi mencionado no modo observador anteriormente, aqui usaremos o exemplo do divisor de arquivo para ilustrar. O divisor de arquivo pode ter mais de um divisor de arquivo binário e também pode ter um divisor de arquivo de texto, um divisor de arquivo de imagem, um divisor de arquivo de vídeo, etc. Em face de diferentes necessidades, muitas vezes é necessário criar diferentes tipos específicos.
classe ISplitter { public : virtual void split () = 0 ; virtual ~ ISplitter () {} }; classe BinarySplitter: public ISplitter { }; classe TxtSplitter: public ISplitter { }; classe PictureSplitter: public ISplitter { }; classe VideoSplitter: public ISplitter { }; classe MainForm: public Form { TextBox * txtFilePath; Caixa de texto* txtFileNumber; ProgressBar * progressBar; public : void Button1_Click () { ISplitter * splitter = new BinarySplitter (); // 依赖 具体 类 splitter-> split (); } };
Porém, uma vez que o design seja alterado dessa maneira, o código deverá ser constantemente alterado e o divisor dependerá da classe de implementação específica.
Usar o modo de fábrica pode resolver esse problema. Define uma interface para criar objetos e permite que as subclasses decidam qual classe instanciar. Os métodos de fábrica atrasam a instanciação de uma classe para subclasses.
// 抽象类 classe iSplitter { público : virtual vazio split () = 0 ; virtual ~ ISplitter () {} }; // 工厂基类 classe SplitterFactory { público : virtual iSplitter * CreateSplitter () = 0 ; virtual ~ SplitterFactory () {} }; // 具体类 classe BinarySplitter: pública iSplitter { }; classe TxtSplitter: public ISplitter { }; classePictureSplitter: public ISplitter { }; classe VideoSplitter: public ISplitter { }; // 具体工厂 classe BinarySplitterFactory: pública SplitterFactory { público : virtual iSplitter * CreateSplitter () { retornar novo BinarySplitter (); } }; classe TxtSplitterFactory: public SplitterFactory { public : virtual ISplitter * CreateSplitter () { retorna novo TxtSplitter (); } }; classe PictureSplitterFactory: public SplitterFactory { public : virtual ISplitter * CreateSplitter () { retorna novo PictureSplitter (); } }; classe VideoSplitterFactory: public SplitterFactory { public : virtual ISplitter * CreateSplitter () { retorna novo VideoSplitter (); } }; classe MainForm: public Form { SplitterFactory * factory; // 工厂 public: O MainForm (SplitterFactory * Factory) { a este -> Fábrica = fábrica; // distinguir parâmetro membro função } anular o Button1_Click () { iSplitter * Splitter = fábrica> CreateSplitter (); // polimórfica nova nova Splitter> Split () ; } }; // MainForm não depende mais de classes concretas
Estrutura
Resumo dos pontos principais
- O padrão Factory Method é usado para isolar o relacionamento de acoplamento entre o usuário do objeto de classe e o tipo específico . Diante de um tipo específico que muda frequentemente, o acoplamento rígido (novo) pode levar a um software frágil.
- O padrão Factory Method usa uma abordagem orientada a objetos para adiar o trabalho dos objetos específicos a serem criados para subclasses, implementando uma estratégia de extensão (em vez de mudança), que resolve melhor esse relacionamento fortemente acoplado.
- O modelo do Método de Fábrica atende às necessidades de mudança de "objetos únicos". A desvantagem é que o método / parâmetros de criação são os mesmos.
Código básico
#include <iostream> usando o namespace std; classe Produto { public : virtual ~ Product () {} virtual void Operation () = 0 ; }; classe ConcreteProductA: public Produto { public : void Operation () {cout << " ConcreteProductA " << endl; } }; classe ConcreteProductB: public Produto { public : void Operation () {cout << "ConcreteProductB " << endl;} }; class Creator { public : produto virtual * FactoryMethod () = 0 ; virtual ~ Creator () {} }; class ConcreteCreatorA: public Creator { public : Product * FactoryMethod () { return new ConcreteProductA ( );} }; classe ConcreteCreatorB: pública Creator { público : Produtos * FactoryMethod () { retornar novoConcreteProductB (); } }; int main () { Criador * ca = novo ConcreteCreatorA (); Produto * pa = ca-> FactoryMethod (); pa -> Operação (); // ConcreteProductA Creator * cb = new ConcreteCreatorB (); Produto * pb = cb-> FactoryMethod (); pb -> Operação (); // ConcreteProductB delete ca; excluir pa; excluir cb; delete pb; retornar 0 ; }