```plantuml interface Product interface ProductFactory Product : use() ProductB : use() ProductA : use() ProductFactory : Product createProduct() ProductAFactory : Product createProduct() ProductBFactory : Product createProduct() Processor : ProductFactory pf Processor : process() Product <|-- ProductA Product <|-- ProductB ProductFactory <|-- ProductAFactory ProductFactory <|-- ProductBFactory ProductA <-- ProductAFactory : creates ProductB <-- ProductBFactory : creates ProductFactory o-- Processor Product <-- Processor : uses ``` The value of this design pattern is that the `Processor` creating and using a product is fully decoupled from the exact type of product, because even the _factory_ is just a generic interface that creates a product from the Processor's point-of-view: ```java interface Product { void use(); } interface ProductFactory { Product createProduct(); } private class ProductA { void use() {...} } class ProductAFactory { Product createProduct() { return new ProductA(); } } private class ProductB { void use() {...} } class ProductBFactory { Product createProduct() { return new ProductB(); } } class Processor { ProductFactory factory; Processor(ProductFactory pf) { factory = pf; } void process() { Product p = factory.createProduct(); p.use() } } class ConsumerA { void main() { Processor p = new Processor(new ProductAFactory()); p.process(); } } class ConsumerB { void main() { Processor p = new Processor(new ProductBFactory()); p.process(); } } ``` With an abstract factory as above, only the client code (in the `main` functions above) needs to be changed if products (and their factories) are added or removed. This defers the decision which product to build, when the choice might become natural, without the need of a switch/if-else statement. In contrast, the _**Simple** Factory Method_ takes the target type as input parameter and can be used with some kind of switch/if-else statement to decide what product to build: ```java class SimpleProductFactory { static Product createProduct(char type) { switch (type) { case 'A': return new ProductA(); case 'B': return new ProductB(); default: throw new Exception("unknown type: " + type); } } } ``` A Simple Factory Method encapsulates the complex logic of creating objects, so just as with the full-blown FM design pattern, changes to the logic of creating objects won’t require changes to the client code. Note that the product type being created and used leaks to the site of processing in the form of the `type` parameter. Therefore, a Simple FM is not a design pattern - it is just an encapsulation of a piece of code so that it can be reused. It provides only one way of creating objects, and hence if you want to create objects in other ways, you have to modify the factory itself, which is the strength of factory method design pattern. In **Python**, you can use duck-typing or subclass from `typing.Protocol`, which works like structural subtyping with **Golang** interfaces: ```go type Product interface { Print() } type productA struct { name string value string } func (df *productA) Print() { fmt.Println("productA ->", df.name, ":", df.value) } type productB struct { name string value string } func (df *productB) Print() { fmt.Println("productB ->", df.name, ":", df.value) } type ProductFactory interface { Create(name, value string) dataField } type product1Factory struct{} func (factory *productAFactory) Create(name, value string) Product { return &productA{ name: name, value: value, } } func NewProductAFactory() ProductFactory { return &productAFactory{} } type product2Factory struct{} func (factory *productBFactory) Create(name, value string) Product { return &productB{ name: name, value: value, } } func NewProductBFactory() ProductFactory { return &productBFactory{} } ``` ```