系列文章
目录
1.简介
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,即定义一个用于创建对象的接口,让子类决定应该实例化哪个类,使类的实例化延迟到子类。 也可以这样理解,
工厂模式可以分为三类:
1.简单工厂模式(Simple Factory)
2.工厂方法模式(Factory Method)
3.抽象工厂模式(Abstract Factory)
2.简单工厂模式
2.1 简介
简单工厂模式是通过一个工厂类将所有对象的创建封装起来,通过传入不同的参数,工厂负责创建不同的具体对象。
建立对象的类是工厂,被建立的对象是产品,使用产品的人无需关心这个产品是怎样生产的,这样便降低了模块之间的耦合。
2.1.1 组成结构
1.工厂类:用来创建所有产品,通过传入的type不同,从而创建不同的产品。例如:本节案例代码中的Factory类。
2.抽象产品类:它一般是具体产品继承的父类或者实现的接口。例如:本节案例代码中的Car类。
3.具体产品类:此类继承抽象产品类,自工厂类所创建的对象就是此角色的实例。例如:本节案例代码中的CarA类和CarB类。
特点:一个工厂生产所有的具体产品。
2.1.2 优点和缺点
优点:
1.将所有对象的创建集合到了一个工厂类中,客户端只需要调用工厂类的接口,传入不同的参数,而无需关注具体对象的创建过程。
2.可以通过工厂类创建不同的对象,而客户端无需改动,实现了客户端和具体所有对象的解耦,提高了代码的灵活性。
缺点:
1.每新增一个产品,则需要修改工厂类的逻辑,违反了开闭原则。
2.当产品足够多的时候,代码会过于臃肿,不利于维护。
2.1.3 应用场景
1.需要根据不同的参数类型创建不同的对象时。
2.2 代码案例
当前代码场景:
我们现在一个工厂要生产车型A和车型B
2.2.1 主要步骤
第一步:创建抽象产品类Car和创建抽象run函数
第二步:创建具体产品类车型A(CarA),实现其抽象run函数。
第三步:创建具体产品类车型B(CarB),实现其抽象run函数
第四步:创建工厂类Factory,并书写根据不同参数创建不同车型的createCar方法。
第五步:客户端(此例是main.cpp调用)创建工厂类对象,通过传递不同的参数,工厂创建不同的对象并返回给客户。
2.2.2 代码
// 抽象产品类 class Car { public: virtual void run() = 0; // 抽象共同接口 string cartype; }; // 具体产品类:车A class CarA : public Car { public: CarA() { cartype = "A 车"; } virtual void run() { std::cout << "this is cartype = " << cartype << endl; } }; // 具体产品类:车B class CarB : public Car { public: CarB() { cartype = "B 车"; } virtual void run() { std::cout << "this is cartype = " << cartype << endl; } }; // 工厂类 class Factory { public: Car *createCar(int type) { switch (type) { case CAR_TYPE_A: return new CarA(); break; case CAR_TYPE_B: return new CarB(); break; default: return nullptr; break; } } }; int main() { Factory *mFactory = new Factory(); // c创建工厂类 Car *acar = mFactory->createCar(CAR_TYPE_A); // 根据具体的参数创建对应的对象,此处是父类指针指向子类对象 Car *bcar = mFactory->createCar(CAR_TYPE_B); acar->run(); bcar->run(); // 注意析构 delete acar; delete bcar; delete mFactory; return 0; }
3.工厂方法模式
3.1简介
工厂方法模式在简单工厂模式的基础上,去掉了简单工厂模式中的创建所有对象的方法,并提供了一个抽象生产产品的接口,并使其它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。
简单工厂模式的特点是一个工厂只生产所有产品,而工厂方法模式则是一个工厂只生产一个产品,这样当生产产品的时候,只需要确定是哪个工厂即可。
3.1.1 组成结构
1.抽象工厂类:是具体工厂类的父类,其包含一个具体工厂类必须实现的抽象接口。例如:本节案例代码的Factory类,抽象接口是createCar函数。
2.具体工厂类:对应其具体产品,用以创建对应的具体产品的对象。例如:本节案例代码的工厂A和工厂B,工厂A负责生产车型A, 工厂B负责生产车型B。
3.抽象产品类:它是具体产品继承的父类。例如:本节案例代码的Car类。
4.具体产品类:具体工厂类所创建的对象就是此类的实例。例如:本节案例代码的车型A类和车型B类。
3.1.2 优点和缺点
优点:
1.当需要增加新的工厂和产品的时候,可以不用更改现有代码,增加了代码的可扩展性,将对象的创建和使用进行了解耦。
缺点:
1.当产品种类过多时,由于每一种产品都需要实现一个工厂类,增加代码复杂性。
3.1.3 应用场景
当只有一类产品时。同时客户端需要生成不同的对象。
3.2 代码案例
此时场景为:
A工厂生产车型A,B工厂生产车型B
3.2.1 主要步骤
第一步:创建抽象产品类(Car类)。
第二步:创建抽象产品类的两个子类(CarA类和CarB类),其子类是具体产品类。
第三步:创建抽象工厂类(Factory类),并提供生产对象的抽象接口。
第四步:创建两个具体工厂类,一个是生产CarA的工厂类,一个是生产CarB的工厂类,并实现抽象方法,创建不同的产品对象。
第五步:客户端(此例是main.cpp调用)创建不同的工厂类对象,从而创建出多个不同的产品对象。
3.2.2 代码
// 抽象产品类 class Car { public: virtual void run() = 0; // 抽象共同接口 string cartype; }; // 具体产品类:车A class CarA : public Car { public: CarA() { cartype = "A 车"; } virtual void run() { std::cout << "this is cartype = " << cartype << endl; } }; // 具体产品类:车B class CarB : public Car { public: CarB() { cartype = "B 车"; } virtual void run() { std::cout << "this is cartype = " << cartype << endl; } }; // 抽象工厂类 class Factory { public: virtual Car *createCar() = 0; }; // 具体工厂类:工厂A(对应产品A) class FactoryA : public Factory { public: virtual Car *createCar() { return new CarA(); } }; // 具体工厂类:工厂B(对应产品B) class FactoryB : public Factory { public: virtual Car *createCar() { return new CarB(); } }; int main() { Factory *mFactoryA = new FactoryA(); // 创建具体工厂类A Car *acar = mFactoryA->createCar(); // 根据具体的工厂类创建对应的对象,此处是父类指针指向子类对象 acar->run(); Factory *mFactoryB = new FactoryB(); // 创建具体工厂类B Car *bcar = mFactoryB->createCar(); // 根据具体的工厂类创建对应的对象,此处是父类指针指向子类对象 bcar->run(); // 注意析构 delete acar; delete bcar; delete mFactoryA; delete mFactoryB; return 0; }
4.抽象工厂模式
之前的工厂方法模式一个工厂只生产一个产品,而在实际生活中,通过一个工厂会生产多种产品,比如:车的组成需要轮胎和方向盘,那么当出现多个产品的时候,便需要使用抽象工厂模式。
4.1简介
提供一个创建一系列相关或相互依赖的对象接口,而无需指定它们的具体类。其实抽象工厂模式就是多个工厂方法模式,只是因为工厂方法是一个工厂只创建一个产品,而抽象工厂模式是一个工厂创建多个产品。
4.1.1 组成结构
抽象工厂类:是具体工厂类的父类,其内部定义了创建多个产品对象的抽象接口,必须由具体工厂类实现。
例如:本节代码案例中的Factory类,抽象接口为createTire和createWheel。
具体工厂类:对应其具体产品,用以创建对应的具体产品的对象。
例如:本节代码案例中的 具体工厂(工厂白色)和具体工厂(工厂黑色)。
抽象产品类:定义了产品的共同接口,具体的产品类必须实现这个接口。工厂模式会由多个产品,因此抽象产品类也是多个。
例如:本节代码案例中的第一个抽象产品类(轮胎)和第二个抽象产品类(方向盘)。
具体产品类:是抽象工厂模式中具体创建的对象。
例如:本节代码案例中的白轮胎和黑轮胎,白方向盘和黑方向盘。
4.1.2 优点和缺点
优点:
创建产品族,将一系列的产品族,统一到一起进行创建
缺点:
扩展困难,当产品族中有新产品,比如新增发动机产品时,需要修改抽象工厂的接口。
4.2 代码案例
现在场景为:
白色工厂需要生产白色轮胎和白色方向盘。
黑色工厂需要生产黑色轮胎和黑色方向盘。
白色系列产品由白色工厂统一管理。
黑色系列产品由黑色工厂统一管理。
4.2.1 主要步骤
第一步:创建第一个抽象产品类(轮胎类)。
第二步:创建第一个抽象产品类的两个子类(白轮胎类和黑轮胎类),其子类是具体产品类。
第三步:创建第二个抽象产品类(方向盘类)。
第四步:创建第二个抽象产品类的两个子类(白方向盘类和黑方向盘类),其子类是具体产品类。
第五步:创建抽象工厂类(Factory类),并提供生产所有对象的两个抽象接口。
第六步:创建两个具体工厂类,一个是生产白色产品的白色工厂类,一个是生产黑色产品的白色工厂类,并实现两个抽象方法,创建不同的产品对象。
第七步:客户端(此例是main.cpp调用)创建不同的工厂类对象,从而创建出多个不同的产品对象。
4.2.2 代码
// 第一个抽象产品类:轮胎 class Tire { public: virtual void whcihtype() = 0; string Tiretype; }; // 第一个抽象产类的第一个具体产品类:白轮胎 class WhiteTire : public Tire { public: WhiteTire() { Tiretype = "白色轮胎"; } virtual void whcihtype() { std::cout << "this is Tiretype = " << Tiretype << endl; } }; // 第一个抽象产类的第二个具体产品类:黑轮胎 class BlackTire : public Tire { public: BlackTire() { Tiretype = "黑色轮胎"; } virtual void whcihtype() { std::cout << "this is Tiretype = " << Tiretype << endl; } }; // 第二个抽象产品类:方向盘 class Wheel { public: virtual void whcihtype() = 0; string Wheeltype; }; // 第二个抽象产类的第一个具体产品类:白色方向盘 class WhiteWheel : public Wheel { public: WhiteWheel() { Wheeltype = "白色方向盘"; } virtual void whcihtype() { std::cout << "this is Wheeltype = " << Wheeltype << endl; } }; // 第二个抽象产类的第二个具体产品类:黑色方向盘 class BlackWheel : public Wheel { public: BlackWheel() { Wheeltype = "黑色方向盘"; } virtual void whcihtype() { std::cout << "this is Wheeltype = " << Wheeltype << endl; } }; // 抽象工厂类 class Factory { public: virtual Tire *createTire() = 0; // 抽象接口 virtual Wheel *createWheel() = 0; }; // 具体工厂类:工厂白色(对应生产白色轮胎和白色方向盘) class FactoryWhite : public Factory { public: virtual Tire *createTire() { return new WhiteTire(); // 生产白轮胎 } virtual Wheel *createWheel() { return new WhiteWheel(); // 生产白方向盘 } }; // 具体工厂类:工厂黑色(对应生产黑色轮胎和黑色方向盘) class FactorBlock : public Factory { public: virtual Tire *createTire() { return new BlackTire(); // 生产黑轮胎 } virtual Wheel *createWheel() { return new BlackWheel(); // 生产黑方向盘 } }; int main() { Factory *mFactoryWhite = new FactoryWhite(); // 创建具体工厂类:工厂白色 Tire *mWhiteTire = mFactoryWhite->createTire(); // 创建白色轮胎 mWhiteTire->whcihtype(); Wheel *mWhiteWheel = mFactoryWhite->createWheel(); // 创建白色方向盘 mWhiteWheel->whcihtype(); Factory *mFactoryBlock = new FactorBlock(); // 创建具体工厂类:工厂黑色 Tire *mBlockTire = mFactoryBlock->createTire(); // 创建黑色轮胎 mBlockTire->whcihtype(); Wheel *mBlockWheel = mFactoryBlock->createWheel(); // 创建黑色方向盘 mBlockWheel->whcihtype(); // 注意析构 delete mFactoryWhite; delete mWhiteTire; delete mWhiteWheel; delete mFactoryBlock; delete mBlockTire; delete mBlockWheel; return 0; }
5.区别
简单工厂模式:
一个抽象产品类,可以派生出多个具体产品类。
无抽象工厂类,只有一个工厂类,此工厂类负责生产所有产品。
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
总结:
抽象产品类:工厂方法模式和简单工厂模式都只有一个抽象产品类,而抽象工厂模式有多个。
具体产品类:工厂方法模式和简单工厂模式都只能有一个抽象产品类派生出多个具体产品类,而抽象工厂模式可以从多个抽象产品类派生出多个具体产品类。
抽象工厂类:工厂方法模式和抽象工厂模式都有一个抽象工厂类,而简单工厂模式没有。
具体工厂类:简单工厂模式只有一个工厂类,而工厂方法模式和抽象工厂模式可以有多个具体工厂类。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。