设计模式
01 简单工厂模式
概念
简单工厂模式:
定义一个简单工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
基本流程:
- 设计一个抽象产品类,它包含一些公共方法的实现
- 从抽象产品中派生出多个具体产品类,如篮球、足球、排球,具体产品类中实现产品生产相关的代码
- 设计一个工厂类,工厂类中提供一个生产各种产品的工厂方法,该方法根据传入参数(产品名称)创建不同具体产品类对象
- 客户只需要调用工厂类的工厂方法,并传入具体产品参数,即可得到一个具体的产品对象
三大角色:
- 工厂factory:根据客户提供的具体产品参数,创建具体产品的实例
- 抽象产品abstract product:具体产品的基类,包含创建产品的公共方法
- 具体产品 concrete product:抽象产品的派生类,包含具体产品特有实现方法,是简单工厂模式的创建目标
优点:
- 工厂类提供创建产品的方法,并包含一定的判断逻辑,客户不必参与产品的创建过程
- 客户只需要直到对应产品参数即可,参数一般简单好记
缺点:
- 新建类的时候会破坏开闭原则(对扩展开放,对修改关闭),即在扩展功能时修改了既有代码。
- 简单工厂模式所有的判断逻辑都在工厂类实现,一旦工厂类设计故障,整个系统都会受之影响!
SimpleFactory.h
#ifndef __SIMPLE_FACTORY__
#define __SIMPLE_FACTORY__
#include <iostream>
#include <string>
using namespace std;
// 抽象产品类AbstractProduct
class AbstractSportProduct {
public:
AbstractSportProduct() {}
// 抽象方法
void printName() {};
void play() {};
};
// 具体产品类Basketball
class Basketball : public AbstractSportProduct {
public:
Basketball() {
printName();
play();
}
// 具体实现方法
void printName() { cout << "获得篮球" << endl; }
void play() { cout << "玩耍篮球" << endl; }
};
class Football : public AbstractSportProduct {
public:
Football() {
printName();
play();
}
// 具体实现方法
void printName() { cout << "获得足球" << endl; }
void play() { cout << "玩耍足球" << endl; }
};
class Volleyball : public AbstractSportProduct {
public:
Volleyball() {
printName();
play();
}
// 具体实现方法
void printName() { cout << "获得排球" << endl; }
void play() { cout << "玩耍排球" << endl; }
};
class Factory {
public:
AbstractSportProduct *getSportProduct(string productname) {
AbstractSportProduct *pro = NULL;
if (productname == "Basketball") pro = new Basketball();
else if (productname == "Football") pro = new Football();
else if (productname == "Volleyball") pro = new Volleyball();
return pro;
}
};
#endif __SIMPLE_FACTORY__
SimpleFactory.cpp
#include <iostream>
#include <string>
#include "SimpleFactory.h"
using namespace std;
int main() {
cout << "简单工厂模式:" << endl;
// 定义工厂对象
Factory *fac = new Factory();
AbstractSportProduct *product = NULL;
product = fac->getSportProduct("Basketball");
product = fac->getSportProduct("Football");
product = fac->getSportProduct("Volleyball");
system("pause");
return 0;
}
02 工厂方法模式
简单工厂模式违背了"开闭原则",每当增加新的产品是,需要修改工厂类的逻辑。为避免这种不足,同时很好的利用简单工厂模式的优点,可以使用工厂方法模式。工厂方法模式中不再使用工厂类统一创建所有的具体产品,而是针对不同的产品设计了不同的工厂,每个工厂只生产特定的产品。
概念
工厂方法模式:
定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
四大角色:
- 抽象工厂AbstractFactory:所有生产具体产品的工厂的基类,提供工厂类的公共方法
- 具体工厂ConcreteFactory:生产具体的产品
- 抽象产品AbstractProduct:所有产品的基类,提供产品类的公共方法
- 具体产品ConcreteProduct:具体的产品类
如果需要添加新的产品,只需要添加一个新产品的工厂,在客户端代码修改具体的工厂类的类名,原有的类的代码无序修改。符合开闭原则,使用频率最高的设计模式,API类库的核心。
优点:
- 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;
- 工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象内部,多态性设计是工厂方法模式的关键;
- 新加入产品时,无需修改原有代码,增强了系统的可扩展性,符合开闭原则。
缺点:
- 添加新产品时需要同时添加新的产品工厂,系统中类的数量成对增加,增加了系统的复杂度,更多的类需要编译和运行,增加了系统的额外开销;
- 工厂和产品都引入了抽象层,客户端代码中均使用的抽象层(AbstractFactory和AbstractSportProduct ),增加了系统的抽象层次和理解难度。
使用环境:
- 客户端不需要知道它所需要创建的对象的类;
- 抽象工厂类通过其子类来指定创建哪个对象(运用多态性设计和里氏代换原则)
FactoryMethod.h
#ifndef __FACTORY_METHOD__
#define __FACTORY_METHOD__
#include <iostream>
#include <string>
using namespace std;
// 定义抽象产品类AbstractSportProduct,方法不提供实现
class AbstractSportProduct {
public:
AbstractSportProduct() {}
void printName() {};
void play() {};
};
// 定义三个具体产品类
class Basketball :public AbstractSportProduct {
public:
Basketball() {
printName();
play();
}
void printName() { cout << "获得篮球" << endl; }
void play() { cout<< "玩耍篮球" <<endl; }
};
class Football :public AbstractSportProduct {
public:
Football() {
printName();
play();
}
void printName() { cout << "获得足球" << endl; }
void play() { cout << "玩耍足球" << endl; }
};
class Volleyball :public AbstractSportProduct {
public:
Volleyball() {
printName();
play();
}
void printName() { cout << "获得排球" << endl; }
void play() { cout << "玩耍排球" << endl; }
};
// 定义抽象工厂类AbstractFactory,方法为纯虚方法
class AbstractFactory {
public:
virtual AbstractSportProduct *getSportProduct() = 0;
};
// 定义三个具体工厂类
class BasketballFactory :public AbstractFactory {
public:
BasketballFactory() {
cout << "篮球工厂:" << endl;
}
AbstractSportProduct *getSportProduct() {
cout << "从篮球工厂获得篮球!" << endl;
return new Basketball();
}
};
class FootballFactory :public AbstractFactory {
public:
FootballFactory() {
cout << "足球工厂:" << endl;
}
AbstractSportProduct *getSportProduct() {
cout << "从足球工厂获得足球!" << endl;
return new Football();
}
};
class VolleyballFactory :public AbstractFactory {
public:
VolleyballFactory() {
cout << "排球工厂:" << endl;
}
AbstractSportProduct *getSportProduct() {
cout << "从排球工厂获得排球!" << endl;
return new Volleyball();
}
};
#endif __FACTORY_METHOD__
FactoryMethod.cpp
#include <iostream>
#include "FactoryMethod.h"
// 客户端使用方法示例
int main() {
cout << "工厂方法模式:" << endl;
AbstractFactory *fac = NULL;
AbstractSportProduct *product = NULL;
fac = new BasketballFactory();
product = fac->getSportProduct();
fac = new FootballFactory();
product = fac->getSportProduct();
fac = new VolleyballFactory();
product = fac->getSportProduct();
system("pause");
return 0;
}
03 抽象工厂模式
- 简单工厂模式所有逻辑都封装在工厂类中,工厂根据客户提供的产品名字创建对应产品的对象实例;
- 工厂方法模式将产品的创建过程放到了具体工厂类中,每一个工厂可以创建一个具体产品,由此可能会创建许多工厂类。
- 抽象工厂模式中一个工厂不只是生产一种产品,而是生产一类产品,可以把这些相关的产品归纳为一个“产品族”,由同一个工厂来生产。
概念
抽象工厂模式:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
四大角色
- 抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法;
- 具体工厂(ConcreteFactory):生产具体的产品
- 抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
- 具体产品(ConcreteProduct):具体的产品类
优点:
- 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;
- 新加入产品系列时,无需修改原有系统,增强了系统的可扩展性,符合开闭原则。
缺点:
- 在已有产品系列中添加新产品时需要修改抽象层代码,对原有系统改动较大,违背开闭原则
适用环境:
- 一系列/一族产品需要被同时使用时,适合使用抽象工厂模式;
- 产品结构稳定,设计完成之后不会向系统中新增或剔除某个产品
AbstractFactory.h
#ifndef __ABSTRACT_FACTORY__
#define __ABSTRACT_FACTORY__
#include <iostream>
#include <string>
using namespace std;
// 抽象产品类AbstractBall, 球类的基类,定义抽象方法play
class AbstractBall {
public:
AbstractBall(){}
void play() {}
};
// 具体产品类, 分别为Basketball和Football,具体实现方法play
class Basketball :public AbstractBall {
public:
Basketball() {
play();
}
void play() {
cout << "玩耍篮球" << endl;
}
};
class Football :public AbstractBall {
public:
Football() {
play();
}
void play() { cout << "玩耍足球" << endl; }
};
// 抽象产品类AbstractShirt:球衣类的基类,定义抽象方法wearShirt
class AbstractShirt
{
public:
AbstractShirt() {}
//抽象方法:
void wearShirt() {};
};
// 具体产品类BasketballShirt和FootballShirt,具体实现方法wearShirt
class BasketballShirt :public AbstractShirt
{
public:
BasketballShirt() {
wearShirt();
}
void wearShirt() { cout << "穿着篮球服" << endl; }
};
class FootballShirt :public AbstractShirt
{
public:
FootballShirt() {
wearShirt();
}
void wearShirt() { cout << "穿着足球服" << endl; }
};
// 定义抽象工厂AbstractFactory,声明两个方法getBall和getShirt
class AbstractFactory
{
public:
virtual AbstractBall *getBall() = 0;
virtual AbstractShirt *getShirt() = 0;
};
// 定义具体工厂BasketballFactory和FootballFactory,重新具体实现两个方法getBall和getShirt
class BasketballFactory :public AbstractFactory
{
public:
BasketballFactory(){ cout << "获得篮球" << endl; }
AbstractBall *getBall(){
cout << "获得篮球" << endl;
return new Basketball();
}
AbstractShirt *getShirt(){
cout << "穿着篮球服" << endl;
return new BasketballShirt();
}
};
class FootballFactory :public AbstractFactory
{
public:
FootballFactory(){ cout << "足球工厂" << endl; }
AbstractBall *getBall(){
cout << "获得足球" << endl;
return new Football();
}
AbstractShirt *getShirt(){
cout << "穿着足球服" << endl;
return new FootballShirt();
}
};
#endif __ABSTRACT_FACTORY__
AbstractFactory.cpp
#include <iostream>
#include "AbstractFactory.h"
// 客户端使用方法示例
int main() {
printf("抽象工厂模式\n");
//定义工厂类对象和产品类对象
AbstractFactory *fac = NULL;
AbstractBall *ball = NULL;
AbstractShirt *shirt = NULL;
fac = new BasketballFactory();
ball = fac->getBall();
shirt = fac->getShirt();
fac = new FootballFactory();
ball = fac->getBall();
shirt = fac->getShirt();
system("pause");
return 0;
}
04 建造者模式
概念
建造者模式:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
四大角色
- 抽象建造者(AbstractBuilder):创建一个Product对象的各个部件指定的抽象接口;
- 具体建造者(ConcreteBuilder):实现AbstractBuilder的接口,实现各个部件的具体构造方法和装配方法,并返回创建结果;
- 产品(Product):具体的产品对象;
- 指挥者(Director):构建一个使用Builder接口的对象,安排复杂对象的构建过程,客户端一般只需要与Director交互,指定建造者类型,然后通过构造函数或者setter方法将具体建造者对象传入Director。它主要的作用是:隔离客户与对象的生产过程,并负责控制产品对象的生产过程。
优点:
- 建造者模式中,客户端不足要知道产品内部组成细节,将产品本身和产品的创建过程分离,使同样的创建过程可以创建不同的产品对象;
- 不同建造者相互独立,并无任何挂链,方便替换。
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围收到一定的限制;
- 如果产品内部变化复杂,可能会导致需要定义很多具体见在这类来实现这种变化,导致系统变得很庞大。
适用环境:
- 需要生产的产品对象有复杂的内部结构(通常包含很多个成员变量)
- 产品对象内部属性具有一定的生成顺序;
- 同一个创建流程适用于多种不同的产品。
BuilderPattern.h
#ifndef __BUILDER_PATTERN__
#define __BUILDER_PATTERN__
#include <iostream>
#include <string>
using namespace std;
// 定义产品类House
class House {
public:
House() {}
void setFloor(string iFloor) { this->floor = iFloor; }
void setWall(string iWall) { this->wall = iWall; }
void setRoof(string iRoof) { this->roof = iRoof; }
void printHouseInfo() {
cout << this->floor << endl;
cout << this->wall << endl;
cout << this->roof << endl;
}
private:
string floor;
string wall;
string roof;
};
// 定义抽象建造者AbstractBuilder
class AbstractBuilder {
public:
AbstractBuilder() { house = new House; }
virtual void builderFloor() = 0;
virtual void builderWall() = 0;
virtual void builderRoof() = 0;
virtual House *getHouse() = 0;
House *house;
};
// 定义具体的建造者
class ConcreteBuilderA :public AbstractBuilder {
public:
ConcreteBuilderA() { cout << "ConcreteBuilderA" << endl; }
void builderFloor() { this->house->setFloor("Floor_A"); }
void builderWall() { this->house->setWall("Floor_A"); }
void builderRoof() { this->house->setRoof("Roof_A"); }
House *getHouse() { return this->house; }
};
class ConcreteBuilderB :public AbstractBuilder {
public:
ConcreteBuilderB() { cout << "ConcreteBuilderB" << endl; }
void builderFloor() { this->house->setFloor("Floor_B"); }
void builderWall() { this->house->setWall("Floor_B"); }
void builderRoof() { this->house->setRoof("Roof_B"); }
House *getHouse() { return this->house; }
};
// 定义指挥者
class Director {
public:
Director(){}
void setBuilder(AbstractBuilder *iBuilder) { this->builder = iBuilder; }
// 封装组装流程,返回建造结果
House *constructor() {
builder->builderFloor();
builder->builderWall();
builder->builderRoof();
return builder->getHouse();
}
private:
AbstractBuilder *builder;
};
#endif __BUILDER_PATTERN__
BuilderPattern.cpp
#include "BuilderPattern.h"
int main() {
// 抽象建造者
AbstractBuilder *builder;
// 指挥者
Director *director = new Director();
// 产品
House *house;
// 指定具体建造者A
builder = new ConcreteBuilderA();
director->setBuilder(builder);
house = director->constructor();
house->printHouseInfo();
// 指定具体的建造者B
builder = new ConcreteBuilderB();
director->setBuilder(builder);
house = director->constructor();
house->printHouseInfo();
system("pause");
return 0;
}