Design mode_ 05 factory mode

Posted by Meltdown on Fri, 18 Feb 2022 08:33:09 +0100

Factory mode

Simple factory mode

structure

Abstract product: it defines the specification of the product and describes the main characteristics and performance of the product.
Concrete products: subclasses that implement or inherit Abstract products.
Specific factory: provides a method for creating products, through which the caller obtains products.

realization

UML diagram

code

class coffee {
public:
	virtual string getName() {}
	void addMilk() {
		cout << "Add milk" << endl;
	}
	void addSuger() {
		cout << "Add sugar" << endl;
	}
};

class AmericanCoffee : public coffee {
public:
	string getName() {
		return "Cafe Americano";
	}
};

class LatteCoffee : public coffee {
public:
	string getName() {
		return "Cafe Latte";
	}
};

class simpleCoffeeFactory {
public:
	coffee* createCoffee(string type) {
		coffee* coffeetype = NULL;
		if (type == "american")
			coffeetype = new AmericanCoffee();
		else if (type == "latte")
			coffeetype = new LatteCoffee();
		return coffeetype;
	}
};

class coffeeStore {
public:
	coffee* getCoffee(string type) {
		simpleCoffeeFactory* factory = new simpleCoffeeFactory();
		coffee* Coffee = factory->createCoffee(type);
		Coffee->addMilk();
		Coffee->addSuger();
		cout <<Coffee->getName() <<endl;
		return Coffee;
	}
};

Static factory

Set the method of creating objects in the factory class to static;

class simpleCoffeeFactory {
public:
	static coffee* createCoffee(string type) { //Set the method of creating the object to static
		coffee* coffeetype = NULL;
		if (type == "american")
			coffeetype = new AmericanCoffee();
		else if (type == "latte")
			coffeetype = new LatteCoffee();
		return coffeetype;
	}
};

class coffeeStore {
public:
	coffee* getCoffee(string type) {
		coffee* Coffee = simpleCoffeeFactory::createCoffee(type); //Directly call the method without instance factory class
		Coffee->addMilk();
		Coffee->addSuger();
		cout <<Coffee->getName() <<endl;
		return Coffee;
	}
};

shortcoming

It violates the opening and closing principle.

Factory mode

The principle of opening and closing is fully followed.

concept

Define an interface for creating objects, and let subclasses decide which product class objects to instantiate. Delay the instantiation of a product to its subclasses.

structure

Abstract factory: it provides an interface for creating products, through which callers access factory methods of specific factories to create products.
Concrete factory: implement the methods in the abstract factory to complete the creation of specific products.
Abstract product: it defines the specification of the product and describes the main characteristics and performance of the product.
Specific product: implements the interface defined by the abstract product role, which is created by the specific factory and corresponds to the specific factory one by one.

realization

UML diagram

code

#include<iostream>
using namespace std;

//Coffee
class coffee {
public:
	virtual string getName() {
		return NULL;
	}
	void addMilk() {
		cout << "Add milk" << endl;
	}
	void addSuger() {
		cout << "Add sugar" << endl;
	}
};

class AmericanCoffee : public coffee {
public:
	string getName() {
		return "Cafe Americano";
	}
};

class LatteCoffee : public coffee {
public:
	string getName() {
		return "Cafe Latte";
	}
};

//Coffee Factory
class CoffeeFactory {
public:
	virtual coffee* createCoffee() = 0;
};

class AmericanCoffeeFactory : public CoffeeFactory {
public:
	coffee* createCoffee() {
		return new AmericanCoffee();
	}
};

class LatteCoffeeFactory : public CoffeeFactory {
public:
	coffee* createCoffee() {
		return new LatteCoffee();
	}
};

//Coffee shop
class coffeeStore {
private:
	CoffeeFactory* factory = NULL;
public:
	void setFactory(CoffeeFactory* factory) {
		this->factory = factory;
	}
	coffee* getCoffee() {
		coffee* Coffee = factory->createCoffee();
		Coffee->addMilk();
		Coffee->addSuger();
		cout << Coffee->getName() << endl;
		return Coffee;
	}
};

int main() {
	coffeeStore store;
	store.setFactory(new AmericanCoffeeFactory());
	store.getCoffee();
	store.setFactory(new LatteCoffeeFactory());
	store.getCoffee();
	return 0;
}

Advantages and disadvantages

Advantages: meet the opening and closing principle.
Disadvantages: each new product needs to add the corresponding specific factory class and product class to increase the complexity.

Abstract pattern

The factory method mode only considers the production of products of the same level. In real life, many factories are comprehensive factories.
The factory method produces only one grade of products, and the abstract factory produces multiple grades of products.

structure

Abstract factory: it provides an interface for creating products, including multiple methods for creating products, and can create multiple products of different levels..
Concrete factory: implement multiple abstract methods in the abstract factory to complete the creation of specific products.
Abstract product: it defines the specification of the product and describes the main characteristics and performance of the product. The abstract product model has multiple Abstract products..
Concrete product: implements the interface defined by the abstract product role, which is created by the concrete factory and has a many to one relationship with the concrete factory.

realization

UML diagram

code

#include<iostream>
using namespace std;

//Coffee
class Coffee {
public:
	virtual void getName() {}
	void addMilk() {
		cout << "Add milk" << endl;
	}
	void addSuger() {
		cout << "Add sugar" << endl;
	}
};

class AmericanCoffee : public Coffee {
public:
	void getName() {
		cout <<"Cafe Americano" <<endl;
	}
};
class LatteCoffee : public Coffee {
public:
	void getName() {
		cout << "Cafe Latte" << endl;
	}
};

//Desserts
class Dessert {
public:
	virtual void getName() {}
};

class AmericanDessert : public Dessert {
public:
	void getName() {
		cout<< "American dessert" <<endl;
	}
};
class LatteDessert : public Dessert {
public:
	void getName() {
		cout << "Latte dessert" << endl;
	}
};

//Factory class
class Factory {
public:
	virtual Coffee* createCoffee() = 0;
	virtual Dessert* createDessert() = 0;
};

class AmericanFactory : public Factory {
public:
	Coffee* createCoffee() {
		return new AmericanCoffee();
	}
	Dessert* createDessert() {
		return new AmericanDessert();
	}
};

class LatteFactory : public Factory {
public:
	Coffee* createCoffee() {
		return new LatteCoffee();
	}
	Dessert* createDessert() {
		return new LatteDessert();
	}
};

//Coffee shop
class coffeeStore {
private:
	Factory* factory = NULL;
public:
	void setFactory(Factory* factory) {
		this->factory = factory;
	}
	Coffee* getCoffee() {
		Coffee* coffee = factory->createCoffee();
		coffee->getName();
		coffee->addMilk();
		coffee->addSuger();
		return coffee;
	}
	Dessert* getDessert() {
		Dessert* dessert = factory->createDessert();
		dessert->getName();
		return dessert;
	}
};

int main() {
	coffeeStore store;
	store.setFactory(new AmericanFactory());
	store.getCoffee();
	cout << endl;
	store.getDessert();
	cout << endl;
	store.setFactory(new LatteFactory());
	store.getCoffee();
	cout << endl;
	store.getDessert();
	cout << endl;
	return 0;
}

Advantages and disadvantages

advantage

When multiple objects of a product family are designed to work together, ensure that the client always uses only the objects in the same product family.

shortcoming

When a new product needs to be added to the product family, all factory classes need to be modified.
The types of product families at different product levels must be the same.

Usage scenario

Input method for skin. Programs that produce different operating systems.

Mode extension

Simple factory + mode extension is used for decoupling.
Load the full class name in the configuration file in the factory class and store it by creating objects through reflection. If the client needs an object, it can get it directly.

Overview of design patterns

Back to design mode overview

Topics: Design Pattern