创建型模式提供了创建对象的机制,旨在提升已有代码的灵活性和可复用性。
部分插图来自: https://refactoringguru.cn/design-patterns/catalog
简单工厂模式严格来说并不是一种设计模式,而更像是一种编程习惯。简单工厂模式在创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来提供新创建的对象。当这个提供对象接口被定义为静态方法时,简单工厂模式也被称为静态工厂模式。
简单工厂模式包含如下角色:
简单工厂的优点:
简单工厂的缺点:增加新产品时需要修改工厂类的代码,违背了开闭原则(对扩展开放,对修改封闭)。
#include /* 猫基类 */
class Cat {
public:virtual void bark() = 0;virtual ~Cat() = default;
};/* 狸花猫 */
class DragonLi : public Cat {
public:void bark() override {std::cout << "DragonLi: meow~" << std::endl;}
};/* 缅因猫 */
class MaineCoon : public Cat {
public:void bark() override {std::cout << "MaineCoon: meow~" << std::endl;}
};/* 布偶猫 */
class Ragdoll : public Cat {
public:void bark() override {std::cout << "Ragdoll: meow~" << std::endl;}
};/* 静态工厂类 专门用来生产猫咪 */
class SimpleCatFactory {
public:static Cat *CreateCat(const std::string &category) {if (category == "DragonLi") {return new DragonLi();} else if (category == "MaineCoon") {return new MaineCoon();} else {return new Ragdoll();}}
};int main() {Cat *dragonLi = SimpleCatFactory::CreateCat("DragonLi");dragonLi->bark();Cat *maineCoon = SimpleCatFactory::CreateCat("MaineCoon");maineCoon->bark();Cat *ragdoll = SimpleCatFactory::CreateCat("Ragdoll");ragdoll->bark();delete dragonLi;delete maineCoon;delete ragdoll;return 0;
}
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
DragonLi: meow~
MaineCoon: meow~
Ragdoll: meow~
atreus@MacBook-Pro %
工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法接口, 允许子类决定所要实例化对象的类型。工厂方法模式使一个产品类的实例化延迟到工厂的子类中进行。
工厂方法模式包含如下角色:
工厂方法模式的优点:
工厂方法模式的缺点:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度。
#include /* 猫基类 */
class Cat {
public:virtual void bark() = 0;virtual ~Cat() = default;
};/* 狸花猫 */
class DragonLi : public Cat {
public:void bark() override {std::cout << "DragonLi: meow~" << std::endl;}
};/* 缅因猫 */
class MaineCoon : public Cat {
public:void bark() override {std::cout << "MaineCoon: meow~" << std::endl;}
};/* 抽象工厂类 */
class CatFactory {
public:virtual Cat *CreateCat() = 0;virtual ~CatFactory() = default;
};class DragonLiFactory : public CatFactory {
public:Cat *CreateCat() override {return new DragonLi();}
};class MaineCoonFactory : public CatFactory {
public:Cat *CreateCat() override {return new MaineCoon();}
};int main() {CatFactory *dragonLiFactory = new DragonLiFactory();Cat *dragonLi = dragonLiFactory->CreateCat();dragonLi->bark();delete dragonLi;delete dragonLiFactory;CatFactory *maineCoonFactory = new MaineCoonFactory();Cat *maineCoon = maineCoonFactory->CreateCat();maineCoon->bark();delete maineCoon;delete maineCoonFactory;return 0;
}
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
DragonLi: meow~
MaineCoon: meow~
atreus@MacBook-Pro %
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产某个单一的产品,而抽象工厂模式可生产一系列相关的产品。
抽象工厂模式包含如下角色:
抽象工厂方法模式的优点:
抽象工厂方法模式的缺点:代码较为复杂,当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。比如我们在下面代码中添加一个有关驱逐舰的方法,包括抽象工厂在内的工厂类都需要进行修改。
#include /* 战列舰基类 */
class Battleship {
public:virtual void fire() = 0;virtual ~Battleship() = default;
};/* 巡洋舰基类 */
class Cruiser {
public:virtual void fire() = 0;virtual ~Cruiser() = default;
};/* 抽象工厂类 */
class AbstractFactory {
public:virtual Battleship *createBattleship() = 0;virtual Cruiser *createCruiser() = 0;virtual ~AbstractFactory() = default;
};/* 衣阿华级战列舰 美国 */
class Iowa : public Battleship {
public:void fire() override {std::cout << "Iowa: fire!" << std::endl;}
};/* 得梅因级巡洋舰 美国 */
class DesMoines : public Cruiser {
public:void fire() override {std::cout << "DesMoines: fire!" << std::endl;}
};/* 大和级战列舰 日本 */
class Yamato : public Battleship {
public:void fire() override {std::cout << "Yamato: fire!" << std::endl;}
};/* 伊吹级巡洋舰 日本 */
class Ibuki : public Cruiser {
public:void fire() override {std::cout << "Ibuki: fire!" << std::endl;}
};/* 美国工厂类 */
class AmericanFactory : public AbstractFactory {
public:Battleship *createBattleship() override {return new Iowa;}Cruiser *createCruiser() override {return new DesMoines;}
};/* 日本工厂类 */
class JapaneseFactory : public AbstractFactory {
public:Battleship *createBattleship() override {return new Yamato;}Cruiser *createCruiser() override {return new Ibuki;}
};int main() {AbstractFactory *americanFactory = new AmericanFactory;Battleship *iowa = americanFactory->createBattleship();iowa->fire();delete iowa;delete americanFactory;AbstractFactory *japaneseFactory = new JapaneseFactory;Cruiser *ibuki = japaneseFactory->createCruiser();ibuki->fire();delete ibuki;delete japaneseFactory;return 0;
}
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
Iowa: fire!
Ibuki: fire!
atreus@MacBook-Pro %
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
原型模式包含如下角色:
clone()
方法。clone()
方法,它是可被复制的对象。clone()
方法来复制新的对象。#include /* 抽象原型类 */
class Prototype {
public:virtual Prototype *clone() = 0;virtual ~Prototype() = default;
};/* 猫咪类 */
class Cat : public Prototype {
public:Cat() = default;/* 深拷贝 */Cat *clone() override {return new Cat();}/* 浅拷贝 */// Cat *clone() override {// return this;// }
};int main() {Cat *oldCat = new Cat();Cat *newCat = oldCat->clone();std::cout << oldCat << std::endl;std::cout << newCat << std::endl;delete oldCat;delete newCat;return 0;
}
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
0x60000321c040
0x60000321c050
atreus@MacBook-Pro %
单例模式只涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类会提供一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式包含如下角色:
单例设计模式分类两种:
#include /* 通过静态变量实现的单例类 */
class Cat {
private:/* 让构造函数私有以避免类被实例化 */Cat() = default;/* 类对应的唯一的对象 */static Cat *m_instance;public:/* 实例对象的唯一访问方式 */static Cat *getInstance() {return m_instance;}
};/* 静态成员变量需要类内定义类外初始化 */
Cat *Cat::m_instance = new Cat;int main() {Cat *dragonLi = Cat::getInstance();Cat *ragdoll = Cat::getInstance();std::cout << dragonLi << std::endl;std::cout << ragdoll << std::endl;delete dragonLi;delete ragdoll; // 由于两个猫咪实际上是一个单例 所以会发成内存的重复释放return 0;
}
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
0x6000007dc040
0x6000007dc040
main(86372,0x1f801c140) malloc: *** error for object 0x6000007dc040: pointer being freed was not allocated
main(86372,0x1f801c140) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort ./main
atreus@MacBook-Pro %
#include /* 通过静态变量实现的单例类 */
class Cat {
private:/* 类对应的唯一的对象 */static Cat *instance;/* 让构造函数私有以避免类被实例化 */Cat() = default;public:/* 实例对象的唯一访问方式 */static Cat *getInstance() {// 多线程场景下此处需要加锁instance = (instance == nullptr) ? new Cat : instance;return instance;}
};/* 静态成员变量需要类内定义类外初始化 */
Cat *Cat::instance = nullptr;int main() {Cat *dragonLi = Cat::getInstance();Cat *ragdoll = Cat::getInstance();std::cout << dragonLi << std::endl;std::cout << ragdoll << std::endl;delete dragonLi;delete ragdoll; // 由于两个猫咪实际上是一个单例 所以会发成内存的重复释放return 0;
}
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
0x600003c18040
0x600003c18040
main(75509,0x1f801c140) malloc: *** error for object 0x600003c18040: pointer being freed was not allocated
main(75509,0x1f801c140) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort ./main
atreus@MacBook-Pro %
通常,为了避免上述类似的对同一单例的多次释放,可以将单例模式与 RAII 机制结合使用:
/* 以 RAII 方式来控制单例 */
class CatStoreRAII {
public:Cat *m_cat;CatStore() {m_cat = Cat::getInstance();}~CatStore() {delete m_cat;}Cat *getCat() {return m_cat;}
};
将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式包含如下角色:
建造者模式的优点:
建造者模式的缺点:造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制
#include
#include using namespace std;/* 产品类 */
class Cat {
private:string m_leg; // 腿string m_tail; // 尾巴
public:const string &getLeg() const {return m_leg;}void setLeg(const string &leg) {m_leg = leg;}const string &getTail() const {return m_tail;}void setTail(const string &tail) {m_tail = tail;}
};/* 抽象建造者 */
class Builder {
protected:Cat *m_cat = new Cat();public:virtual void buildLeg() = 0;virtual void buildTail() = 0;virtual Cat *createCat() = 0;virtual ~Builder() {delete m_cat;}
};/* 具体构建者 */
class DragonLiBuilder : public Builder {
public:void buildLeg() override {m_cat->setLeg("狸");}void buildTail() override {m_cat->setTail("花");}Cat *createCat() override {return m_cat;}
};/* 具体构建者 */
class RagdollBuilder : public Builder {
public:void buildLeg() override {m_cat->setLeg("布");}void buildTail() override {m_cat->setTail("偶");}Cat *createCat() override {return m_cat;}
};/* 指挥者 */
class Director {
private:Builder *m_builder;public:explicit Director(Builder *builder) {m_builder = builder;}Cat *construct() {m_builder->buildLeg();m_builder->buildTail();return m_builder->createCat();}~Director() {delete m_builder;}
};int main() {Director dragonLiDirector(new DragonLiBuilder);Cat *dragonLi = dragonLiDirector.construct();cout << dragonLi->getLeg() << dragonLi->getTail() << endl;Director ragdollDirector(new RagdollBuilder);Cat *ragdoll = ragdollDirector.construct();cout << ragdoll->getLeg() << ragdoll->getTail() << endl;return 0;
}
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
狸花
布偶
atreus@MacBook-Pro %