设计模式(一)——简单工厂、工厂方法、抽象工厂、建造者模式

设计模式

01 简单工厂模式

简单工厂

概念

简单工厂模式:
定义一个简单工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类

基本流程:

  1. 设计一个抽象产品类,它包含一些公共方法的实现
  2. 从抽象产品中派生出多个具体产品类,如篮球、足球、排球,具体产品类中实现产品生产相关的代码
  3. 设计一个工厂类,工厂类中提供一个生产各种产品的工厂方法,该方法根据传入参数(产品名称)创建不同具体产品类对象
  4. 客户只需要调用工厂类的工厂方法,并传入具体产品参数,即可得到一个具体的产品对象

三大角色

  1. 工厂factory:根据客户提供的具体产品参数,创建具体产品的实例
  2. 抽象产品abstract product:具体产品的基类,包含创建产品的公共方法
  3. 具体产品 concrete product:抽象产品的派生类,包含具体产品特有实现方法,是简单工厂模式的创建目标

优点

  1. 工厂类提供创建产品的方法,并包含一定的判断逻辑,客户不必参与产品的创建过程
  2. 客户只需要直到对应产品参数即可,参数一般简单好记

缺点

  1. 新建类的时候会破坏开闭原则(对扩展开放,对修改关闭),即在扩展功能时修改了既有代码。
  2. 简单工厂模式所有的判断逻辑都在工厂类实现,一旦工厂类设计故障,整个系统都会受之影响!

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 工厂方法模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YNTpg75Z-1600313509658)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200916154440568.png)]

简单工厂模式违背了"开闭原则",每当增加新的产品是,需要修改工厂类的逻辑。为避免这种不足,同时很好的利用简单工厂模式的优点,可以使用工厂方法模式。工厂方法模式中不再使用工厂类统一创建所有的具体产品,而是针对不同的产品设计了不同的工厂每个工厂只生产特定的产品

概念

工厂方法模式:
定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。

四大角色:

  1. 抽象工厂AbstractFactory:所有生产具体产品的工厂的基类,提供工厂类的公共方法
  2. 具体工厂ConcreteFactory:生产具体的产品
  3. 抽象产品AbstractProduct:所有产品的基类,提供产品类的公共方法
  4. 具体产品ConcreteProduct:具体的产品类

如果需要添加新的产品,只需要添加一个新产品的工厂在客户端代码修改具体的工厂类的类名,原有的类的代码无序修改。符合开闭原则,使用频率最高的设计模式,API类库的核心。

优点:

  1. 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂
  2. 工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象内部,多态性设计是工厂方法模式的关键;
  3. 新加入产品时,无需修改原有代码,增强了系统的可扩展性,符合开闭原则

缺点:

  1. 添加新产品时需要同时添加新的产品工厂,系统中类的数量成对增加增加了系统的复杂度,更多的类需要编译和运行,增加了系统的额外开销
  2. 工厂和产品都引入了抽象层,客户端代码中均使用的抽象层(AbstractFactory和AbstractSportProduct ),增加了系统的抽象层次和理解难度

使用环境:

  1. 客户端不需要知道它所需要创建的对象的类;
  2. 抽象工厂类通过其子类来指定创建哪个对象(运用多态性设计和里氏代换原则)

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 抽象工厂模式

抽象工厂模式

  1. 简单工厂模式所有逻辑都封装在工厂类中,工厂根据客户提供的产品名字创建对应产品的对象实例;
  2. 工厂方法模式将产品的创建过程放到了具体工厂类中,每一个工厂可以创建一个具体产品,由此可能会创建许多工厂类。
  3. 抽象工厂模式中一个工厂不只是生产一种产品,而是生产一类产品,可以把这些相关的产品归纳为一个“产品族”,由同一个工厂来生产。

概念

抽象工厂模式:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

四大角色

  1. 抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法;
  2. 具体工厂(ConcreteFactory):生产具体的产品
  3. 抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
  4. 具体产品(ConcreteProduct):具体的产品类

优点:

  1. 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;
  2. 新加入产品系列时,无需修改原有系统,增强了系统的可扩展性,符合开闭原则。

缺点:

  1. 在已有产品系列中添加新产品时需要修改抽象层代码,对原有系统改动较大,违背开闭原则

适用环境:

  1. 一系列/一族产品需要被同时使用时,适合使用抽象工厂模式;
  2. 产品结构稳定,设计完成之后不会向系统中新增或剔除某个产品

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 建造者模式

建造者模式
概念

建造者模式:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

四大角色

  1. 抽象建造者(AbstractBuilder):创建一个Product对象的各个部件指定的抽象接口;
  2. 具体建造者(ConcreteBuilder):实现AbstractBuilder的接口,实现各个部件的具体构造方法和装配方法,并返回创建结果;
  3. 产品(Product):具体的产品对象;
  4. 指挥者(Director):构建一个使用Builder接口的对象,安排复杂对象的构建过程,客户端一般只需要与Director交互,指定建造者类型,然后通过构造函数或者setter方法将具体建造者对象传入Director。它主要的作用是:隔离客户与对象的生产过程,并负责控制产品对象的生产过程。

优点:

  1. 建造者模式中,客户端不足要知道产品内部组成细节,将产品本身和产品的创建过程分离,使同样的创建过程可以创建不同的产品对象;
  2. 不同建造者相互独立,并无任何挂链,方便替换。

缺点:

  1. 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围收到一定的限制;
  2. 如果产品内部变化复杂,可能会导致需要定义很多具体见在这类来实现这种变化,导致系统变得很庞大

适用环境:

  1. 需要生产的产品对象有复杂的内部结构(通常包含很多个成员变量)
  2. 产品对象内部属性具有一定的生成顺序;
  3. 同一个创建流程适用于多种不同的产品。

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值