Resumo:
O padrão de fábrica é um padrão de projeto comum, que pode nos ajudar a organizar e gerenciar melhor o processo de criação de objetos na programação orientada a objetos. Este artigo apresentará o conceito do padrão de fábrica em detalhes, três cenários de aplicação comuns do padrão de fábrica e fornecerá exemplos de código C++ de alta qualidade, com o objetivo de ajudar os iniciantes a entender e aplicar melhor o padrão de fábrica.
1. Visão geral do padrão de fábrica
O padrão de fábrica pertence ao padrão de design criacional, que fornece uma maneira de encapsular o processo de criação de objetos. Por meio do modo de fábrica, podemos desacoplar a instanciação de objetos do código do cliente, de modo que o código do cliente não dependa do método de criação de objeto específico, mas obtenha a instância de objeto necessária por meio da fábrica. Esse desacoplamento ajuda a melhorar a flexibilidade e a capacidade de manutenção do código.
No padrão de fábrica, geralmente existem três funções principais:
Produto Abstrato (Abstract Product): define a interface do produto, e o produto específico deve implementar essas interfaces.
Produto Concreto: implementa a interface definida pelo produto abstrato e representa uma instância de objeto concreto.
Fábrica (Factory): responsável por criar uma instância de um produto específico, sendo que o código cliente obtém o objeto do produto requerido através da fábrica.
2. Cenários de aplicação de padrão de fábrica
2.1 Padrão Simples de Fábrica
O padrão de fábrica simples não é um dos 23 padrões de projeto propostos pelo GOF (Gang of Four), mas é uma forma básica do padrão de fábrica. No padrão de fábrica simples, usamos uma única classe de fábrica que é responsável por criar todos os objetos de produto.
Cena aplicável:
Quando há poucos objetos a serem criados e o processo de criação é relativamente simples, você pode considerar o uso do padrão de fábrica simples.
Aplicável a um grupo de classes com a mesma classe pai ou interface, e o cliente não precisa se preocupar com os detalhes da criação de objetos específicos.
2.2 Padrão de Método de Fábrica (Factory Method Pattern)
O padrão de método de fábrica define uma interface para criar objetos, mas cabe às subclasses decidir qual classe instanciar. Dessa forma, o padrão Factory Method adia a instanciação do objeto para a subclasse, que segue o princípio de abertura e fechamento.
Cena aplicável:
Quando necessitar de adicionar um novo produto, basta criar a respetiva fábrica e categoria de produto específica, sem modificar o código existente, que obedece ao princípio de abertura e fecho.
Aplicável a um grupo de classes com a mesma classe pai ou interface, e cada subclasse precisa de uma lógica de inicialização diferente.
2.3 Padrão Abstrato de Fábrica
O padrão Abstract Factory fornece uma interface para criar uma série de objetos relacionados ou interdependentes sem especificar classes concretas. Ao usar o padrão de fábrica abstrato, os clientes podem criar e usar vários portfólios de produtos sem se preocupar com os detalhes de implementação de produtos específicos.
Cena aplicável:
Aplicável quando existem várias séries de produtos (como diferentes marcas de carros e pneus) e o cliente precisa usar essas séries de produtos.
Ajuda a evitar problemas de incompatibilidade entre produtos e garante que uma gama de produtos seja criada em conjunto.
3. A diferença entre os três modelos de fábrica
O padrão de fábrica simples possui apenas uma classe de fábrica para criar todos os produtos, o padrão de método de fábrica corresponde a uma fábrica específica para cada produto e o padrão de fábrica abstrato corresponde a uma fábrica específica para cada combinação de produto.
O código do cliente do modelo de fábrica simples está fortemente associado ao produto específico, que não obedece ao princípio de abertura e fechamento. O padrão de método de fábrica e o padrão de fábrica abstrato criam novos produtos derivando novas classes de fábrica, que estão mais alinhadas com o princípio de abertura e fechamento.
O padrão Factory Method adia a criação de produtos para subclasses, tornando o sistema mais flexível. O padrão fábrica abstrato fornece uma série de combinações de produtos com base na fábrica, que é mais adequada para criar uma série de produtos relacionados.
4. Exemplo de código C++
4.1 Exemplo de padrão de fábrica simples
// 抽象产品
class Product {
public:
virtual void operation() = 0;
};
// 具体产品 A
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "Concrete Product A" << std::endl;
}
};
// 具体产品 B
class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "Concrete Product B" << std::endl;
}
};
// 简单工厂类
class SimpleFactory {
public:
static Product* createProduct(int type) {
if (type == 1) {
return new ConcreteProductA();
} else if (type == 2) {
return new ConcreteProductB();
}
return nullptr;
}
};
int main() {
Product* productA = SimpleFactory::createProduct(1);
Product* productB = SimpleFactory::createProduct(2);
productA->operation(); // 输出:Concrete Product A
productB->operation(); // 输出:Concrete Product B
delete productA;
delete productB;
return 0;
}
4.2 Exemplo de padrão de método de fábrica
// 抽象产品
class Product {
public:
virtual void operation() = 0;
};
// 具体产品 A
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "Concrete Product A" << std::endl;
}
};
// 具体产品 B
class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "Concrete Product B" << std::endl;
}
};
// 抽象工厂类
class Factory {
public:
virtual Product* createProduct() = 0;
};
// 具体工厂 A
class ConcreteFactoryA : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductA();
}
};
// 具体工厂 B
class ConcreteFactoryB : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductB();
}
};
int main() {
Factory* factoryA = new ConcreteFactoryA();
Factory* factoryB = new ConcreteFactoryB();
Product* productA = factoryA->createProduct();
Product* productB = factoryB->createProduct();
productA->operation(); // 输出:Concrete Product A
productB->operation(); // 输出:Concrete Product B
delete factoryA;
delete factoryB;
delete productA;
delete productB;
return 0;
}
4.3 Exemplo de padrão fábrica abstrato
// 抽象产品 A
class AbstractProductA {
public:
virtual void operationA() = 0;
};
// 具体产品 A1
class ConcreteProductA1 : public AbstractProductA {
public:
void operationA() override {
std::cout << "Concrete Product A1" << std::endl;
}
};
// 具体产品 A2
class ConcreteProductA2 : public AbstractProductA {
public:
void operationA() override {
std::cout << "Concrete Product A2" << std::endl;
}
};
// 抽象产品 B
class AbstractProductB {
public:
virtual void operationB() = 0;
};
// 具体产品 B1
class ConcreteProductB1 : public AbstractProductB {
public:
void operationB() override {
std::cout << "Concrete Product B1" << std::endl;
}
};
// 具体产品 B2
class ConcreteProductB2 : public AbstractProductB {
public:
void operationB() override {
std::cout << "Concrete Product B2" << std::endl;
}
};
// 抽象工厂类
class AbstractFactory {
public:
virtual AbstractProductA* createProductA() = 0;
virtual AbstractProductB* createProductB() = 0;
};
// 具体工厂 1
class ConcreteFactory1 : public AbstractFactory {
public:
AbstractProductA* createProductA() override {
return new ConcreteProductA1();
}
AbstractProductB* createProductB() override {
return new ConcreteProductB1();
}
};
// 具体工厂 2
class ConcreteFactory2 : public AbstractFactory {
public:
AbstractProductA* createProductA() override {
return new ConcreteProductA2();
}
AbstractProductB* createProductB() override {
return new ConcreteProductB2();
}
};
int main() {
AbstractFactory* factory1 = new ConcreteFactory1();
AbstractFactory* factory2 = new ConcreteFactory2();
AbstractProductA* productA1 = factory1->createProductA();
AbstractProductB* productB1 = factory1->createProductB();
AbstractProductA* productA2 = factory2->createProductA();
AbstractProductB* productB2 = factory2->createProductB();
productA1->operationA(); // 输出:Concrete Product A1
productB1->operationB(); // 输出:Concrete Product B1
productA2->operationA(); // 输出:Concrete Product A2
productB2->operationB(); // 输出:Concrete Product B2
delete factory1;
delete factory2;
delete productA1;
delete productB1;
delete productA2;
delete productB2;
return 0;
}
Os exemplos de código acima demonstram, respectivamente, o uso de padrão de fábrica simples, padrão de método de fábrica e padrão de fábrica abstrato, esperando ajudar os leitores a entender e aplicar melhor esses três padrões de fábrica. O uso de padrões de projeto pode tornar nosso código mais flexível, fácil de manter e seguir alguns princípios importantes do projeto orientado a objetos.