Fale sobre o padrão Factory.
sobes.tech IA
Resposta da IA
Uma fábrica é um padrão de design creacional que fornece uma interface comum para criar objetos na superclasse, enquanto que as subclasses podem modificar o tipo de objetos criados.
-
Fábrica simples (Simple Factory): Não é um padrão na sua forma pura, mas sim uma idiomática. Uma classe com um método que cria objetos com base nos parâmetros de entrada.
package main import "fmt" type Product interface { Use() } type ConcreteProductA struct{} func (p *ConcreteProductA) Use() { fmt.Println("A usar Produto Concreto A") } type ConcreteProductB struct{} func (p *ConcreteProductB) Use() { fmt.Println("A usar Produto Concreto B") } type SimpleFactory struct{} func (f *SimpleFactory) CreateProduct(t string) Product { switch t { case "A": return &ConcreteProductA{} case "B": return &ConcreteProductB{} default: return nil } } func main() { factory := SimpleFactory{} productA := factory.CreateProduct("A") productA.Use() productB := factory.CreateProduct("B") productB.Use() } -
Método de fábrica (Factory Method): Define uma interface para criar um objeto, mas permite que as subclasses decidam qual classe instanciar.
package main import "fmt" // Interface do produto type Product interface { Operation() string } // Produto concreto A type ConcreteProduct1 struct{} func (p *ConcreteProduct1) Operation() string { return "Resultado do ConcreteProduct1" } // Produto concreto B type ConcreteProduct2 struct{} func (p *ConcreteProduct2) Operation() string { return "Resultado do ConcreteProduct2" } // Interface do criador type Creator interface { FactoryMethod() Product SomeOperation() string } // Estrutura base do criador type BaseCreator struct{} func (bc *BaseCreator) SomeOperation() string { // Chamada do método de fábrica para obter um objeto de produto product := bc.FactoryMethod() // Uso do produto result := "O código do criador acabou de trabalhar com " + product.Operation() return result } // Criador concreto A type ConcreteCreator1 struct { BaseCreator } func (cc *ConcreteCreator1) FactoryMethod() Product { return &ConcreteProduct1{} // Cria Produto concreto A } // Criador concreto B type ConcreteCreator2 struct { BaseCreator } func (cc *ConcreteCreator2) FactoryMethod() Product { return &ConcreteProduct2{} // Cria Produto concreto B } func main() { // Exemplo de uso creator1 := &ConcreteCreator1{} fmt.Println(creator1.SomeOperation()) creator2 := &ConcreteCreator2{} fmt.Println(creator2.SomeOperation()) } -
Fábrica abstrata (Abstract Factory): Fornece uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.
package main import "fmt" // Interface do produto A type AbstractProductA interface { UseProductA() string } // Produto A1 concreto type ConcreteProductA1 struct{} func (*ConcreteProductA1) UseProductA() string { return "O resultado do produto A1." } // Produto A2 concreto type ConcreteProductA2 struct{} func (*ConcreteProductA2) UseProductA() string { return "O resultado do produto A2." } // Interface do produto B type AbstractProductB interface { UseProductB() string AnotherFunctionB(collaborator AbstractProductA) string // Interação com produto A } // Produto B1 concreto type ConcreteProductB1 struct{} func (*ConcreteProductB1) UseProductB() string { return "O resultado do produto B1." } // Interação B1 com qualquer tipo de AbstractProductA func (*ConcreteProductB1) AnotherFunctionB(collaborator AbstractProductA) string { result := collaborator.UseProductA() return fmt.Sprintf("O resultado do B1 colaborando com o (%s)", result) } // Produto B2 concreto type ConcreteProductB2 struct{} func (*ConcreteProductB2) UseProductB() string { return "O resultado do produto B2." } // Interação B2 com qualquer tipo de AbstractProductA func (*ConcreteProductB2) AnotherFunctionB(collaborator AbstractProductA) string { result := collaborator.UseProductA() return fmt.Sprintf("O resultado do B2 colaborando com o (%s)", result) } // Interface da fábrica abstrata type AbstractFactory interface { CreateProductA() AbstractProductA CreateProductB() AbstractProductB } // Fábrica concreta 1 type ConcreteFactory1 struct{} func (*ConcreteFactory1) CreateProductA() AbstractProductA { return &ConcreteProductA1{} } func (*ConcreteFactory1) CreateProductB() AbstractProductB { return &ConcreteProductB1{} } // Fábrica concreta 2 type ConcreteFactory2 struct{} func (*ConcreteFactory2) CreateProductA() AbstractProductA { return &ConcreteProductA2{} } func (*ConcreteFactory2) CreateProductB() AbstractProductB { return &ConcreteProductB2{} } // Código cliente que trabaja con la fábrica func ClientCode(factory AbstractFactory) { productA := factory.CreateProductA() productB := factory.CreateProductB() fmt.Println(productB.UseProductB()) fmt.Println(productB.AnotherFunctionB(productA)) } func main() { fmt.Println("Cliente: Probando código cliente con el primer tipo de fábrica:") ClientCode(&ConcreteFactory1{}) fmt.Println("Cliente: Probando el mismo código cliente con el segundo tipo de fábrica:") ClientCode(&ConcreteFactory2{}) }
A principal diferença entre o método de fábrica e a fábrica abstrata: O método de fábrica cria produtos individuais, enquanto que a fábrica abstrata cria famílias de produtos.
| Nome do padrão | Descrição | Quando usar |
|---|---|---|
| Fábrica simples | Método numa classe para criar objetos de diferentes tipos. | Para criar objetos simples sem necessidade de uma hierarquia de fábricas. |
| Método de fábrica | Interface para criar um objeto, permitindo que subclasses decidam qual classe instanciar. | Quando uma classe não consegue prever o tipo de objetos que deve criar. |
| Fábrica abstrata | Interface para criar famílias de objetos relacionados. | Quando o sistema deve ser independente do modo como seus produtos são criados e representados. |
O padrão Fábrica promove um baixo acoplamento do código e facilita a adição de novos tipos de produtos sem modificar o código cliente.