设计模式从青铜到王者第七篇:创建型模式之抽象工厂模式(Abstract Factory)

Posted 森明帮大于黑虎帮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式从青铜到王者第七篇:创建型模式之抽象工厂模式(Abstract Factory)相关的知识,希望对你有一定的参考价值。

系列文章目录


文章目录


前言


回顾之前的设计模式,简单工厂模式所有逻辑都封装在工厂类中,工厂根据客户提供的产品名字创建对应产品的对象实例;工厂方法模式将产品的创建过程放到了具体工厂类中,每一个工厂可以创建一个具体产品,由此可能会创建许多工厂类。很多时候,一个工厂不只是生产一种产品,而是生产一类产品,比如一个体育用品工厂,可以生产篮球、足球、排球等多种产品。此时我们可以把这些相关的产品归纳为一个“产品族”,由同一个工厂来生产,这即是Jungle今天要学习的抽象工厂模式。

1.抽象工厂模式简介

抽象工厂模式是常用的创建型设计模式之一。而今天Jungle要学习的抽象工厂模式,其抽象程度更高,每一个具体工厂可以生产一组相关的具体产品对象。

抽象工厂模式定义:

抽象工厂模式:

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

简言之,一个工厂可以提供创建多种相关产品的接口,而无需像工厂方法一样,为每一个产品都提供一个具体工厂。

2.抽象工厂模式结构

抽象工厂模式结构与工厂方法模式结构类似,不同之处在于,一个具体工厂可以生产多种同类相关的产品:

  • 抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法;
  • 具体工厂(ConcreteFactory):生产具体的产品
  • 抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
  • 具体产品(ConcreteProduct):具体的产品类
    抽象工厂模式UML类图如下:

结合抽象工厂模式定义和UML,可以看到具体工厂ConcreteFactory_A可以生产两种产品,分别是ConcreteProduct_A_1和ConcreteProduct_A_2,另一个具体工厂ConcreteFactory_B同理。客户端使用时,需要声明一个抽象工厂AbstractFactory和两个抽象产品AbstractProduct

3.抽象工厂模式代码实例

考虑这样一个场景,如下图:

Jungle想要进行户外运动,它可以选择打篮球和踢足球。
但这次Jungle不想弄脏原本穿的T恤,所以Jungle还需要穿球衣,打篮球就穿篮球衣,踢足球就穿足球衣。
篮球保管室可以提供篮球和篮球衣,足球保管室可以提供足球和足球衣。
Jungle只要根据心情去某个保管室,就可以换上球衣、拿上球,然后就可以愉快地玩耍了。

对应的UML实例图如下图:

3.1.定义产品类

3.1.1.产品类Ball

  • 抽象产品类AbstractBall, 球类的基类,定义抽象方法play
//抽象产品类AbstractBall
class AbstractBall

public:
    AbstractBall()
    //抽象方法:
    virtual void play() = 0;
    virtual ~AbstractBall() 
;
  • 具体产品类, 分别为Basketball和Football,具体实现方法play
//具体产品类Basketball
class Basketball :public AbstractBall

public:
	Basketball()
		play();
	
	//具体实现方法
	void play()
		printf("Jungle play Basketball\\n\\n");
	
;
 
//具体产品类Football
class Football :public AbstractBall

public:
	Football()
		play();
	
	//具体实现方法
	void play()
		printf("Jungle play Football\\n\\n");
	
;

3.1.2.产品类Shirt

  • 抽象产品类AbstractShirt:球衣类的基类,定义抽象方法wearShirt
//抽象产品类AbstractShirt
class AbstractShirt

public:
    AbstractShirt()
    //抽象方法:
    virtual void wearShirt() = 0;
    virtual ~AbstractShirt()
;
  • 具体产品类BasketballShirt和FootballShirt,具体实现方法wearShirt
//具体产品类BasketballShirt
class BasketballShirt :public AbstractShirt

public:
	BasketballShirt()
		wearShirt();
	
	//具体实现方法
	void wearShirt()
		printf("Jungle wear Basketball Shirt\\n\\n");
	
;
 
//具体产品类FootballShirt
class FootballShirt :public AbstractShirt

public:
	FootballShirt()
		wearShirt();
	
	//具体实现方法
	void wearShirt()
		printf("Jungle wear Football Shirt\\n\\n");
	
;

3.2.定义工厂类

  • 定义抽象工厂AbstractFactory,声明两个方法getBall和getShirt
//抽象工厂类
class AbstractFactory

public:
    virtual AbstractBall *getBall() = 0;
    virtual AbstractShirt *getShirt() = 0;
    virtual ~AbstractFactory()
;
  • 定义具体工厂BasketballFactory和FootballFactory,重新具体实现两个方法getBall和getShirt
//具体工厂类BasketballFactory
class BasketballFactory :public AbstractFactory

public:
	BasketballFactory()
		printf("BasketballFactory\\n");
	
	AbstractBall *getBall()
		printf("Jungle get basketball\\n");
		return new Basketball();
	
	AbstractShirt *getShirt()
		printf("Jungle get basketball shirt\\n");
		return new BasketballShirt();
	
;
 
//具体工厂类BasketballFactory
class FootballFactory :public AbstractFactory

public:
	FootballFactory()
		printf("FootballFactory\\n");
	
	AbstractBall *getBall()
		printf("Jungle get football\\n");
		return new Football();
	
	AbstractShirt *getShirt()
		printf("Jungle get football shirt\\n");
		return new FootballShirt();
	
;
  • 完整头文件代码AbstractFactory.h
#ifndef __ABSTRACT_FACTORY__
#define __ABSTRACT_FACTORY__

#include <iostream>
#include <string.h>
using namespace std;

// 抽象产品类AbstractBall
class AbstractBall

public:
	AbstractBall()
	
	
	virtual ~AbstractBall() 
	// 抽象方法:
	virtual void play();
;

// 具体产品类Basketball
class Basketball : public AbstractBall

public:
	Basketball()
	
		play();
	
	// 具体实现方法
	void play()
	
		printf("Jungle play Basketball\\n\\n");
	
;

// 具体产品类Football
class Football : public AbstractBall

public:
	Football()
	
		play();
	
	// 具体实现方法
	void play()
	
		printf("Jungle play Football\\n\\n");
	
;

// 抽象产品类AbstractShirt
class AbstractShirt

public:
	AbstractShirt() 
	virtual ~AbstractShirt() 
	// 抽象方法:
	virtual void wearShirt();
;

// 具体产品类BasketballShirt
class BasketballShirt : public AbstractShirt

public:
	BasketballShirt()
	
		wearShirt();
	
	// 具体实现方法
	void wearShirt()
	
		printf("Jungle wear Basketball Shirt\\n\\n");
	
;

// 具体产品类FootballShirt
class FootballShirt : public AbstractShirt

public:
	FootballShirt()
	
		wearShirt();
	
	// 具体实现方法
	void wearShirt()
	
		printf("Jungle wear Football Shirt\\n\\n");
	
;

// 抽象工厂类
class AbstractFactory

public:
	virtual ~AbstractFactory() 
	virtual AbstractBall *getBall() = 0;
	virtual AbstractShirt *getShirt() = 0;
;

// 具体工厂类BasketballFactory
class BasketballFactory : public AbstractFactory

public:
	BasketballFactory()
	
		printf("BasketballFactory\\n");
	
	AbstractBall *getBall()
	
		printf("Jungle get basketball\\n");
		return new Basketball();
	
	AbstractShirt *getShirt()
	
		printf("Jungle get basketball shirt\\n");
		return new BasketballShirt();
	
;

// 具体工厂类BasketballFactory
class FootballFactory : public AbstractFactory

public:
	FootballFactory()
	
		printf("FootballFactory\\n");
	
	AbstractBall *getBall()
	
		printf("Jungle get football\\n");
		return new Football();
	
	AbstractShirt *getShirt()
	
		printf("Jungle get football shirt\\n");
		return new FootballShirt();
	
;

#endif //__ABSTRACT_FACTORY__

3.3.客户端使用方法示例

#include <iostream>
#include "AbstractFactory.h"
 
int main()

    printf("抽象工厂模式\\n");

    //定义工厂类对象和产品类对象
    AbstractFactory *fac = nullptr;
    AbstractBall *ball = nullptr;
    AbstractShirt *shirt = nullptr;

    fac = new BasketballFactory();
    ball = fac->getBall();
    shirt = fac->getShirt();
    delete ball;
    ball = nullptr;
    delete shirt;
    shirt = nullptr;
    delete fac;
    fac = nullptr;

    fac = new FootballFactory();
    ball = fac->getBall();
    shirt = fac->getShirt();
    delete ball;
    ball = nullptr;
    delete shirt;
    shirt = nullptr;
    delete fac;
    fac = nullptr;

    system("pause");
    return 0;

  • 主代码main.cpp
#ifndef __ABSTRACT_FACTORY__
#define __ABSTRACT_FACTORY__

#include <iostream>
#include <string.h>
using namespace std;

// 抽象产品类AbstractBall
class AbstractBall

public:
	AbstractBall()
	
	
	virtual ~AbstractBall() 
	// 抽象方法:
	virtual void play();
;

// 具体产品类Basketball
class Basketball : public AbstractBall

public:
	Basketball()
	
		play();
	
	// 具体实现方法
	void play()
	
		printf("Jungle play Basketball\\n\\n");
	
;

// 具体产品类Football
class Football : public AbstractBall

public:
	Football()
	
		play();
	
	// 具体实现方法
	void play()
	
		printf("Jungle play Football\\n\\n");
	
;

// 抽象产品类AbstractShirt
class AbstractShirt

public:
	AbstractShirt() 
	virtual ~AbstractShirt() 
	// 抽象方法:
	virtual void wearShirt();
;

// 具体产品类BasketballShirt
class BasketballShirt : public AbstractShirt

public:
	BasketballShirt()
	
		wearShirt();
	
	// 具体实现方法
	void wearShirt()
	
		printf("Jungle wear Basketball Shirt\\n\\n");
	
;

// 具体产品类FootballShirt
class FootballShirt : public AbstractShirt

public:
	FootballShirt()
	
		wearShirt();
	
	// 具体实现方法
	void wearShirt()
	
		printf("Jungle wear Football Shirt\\n\\n");
	
;

// 抽象工厂类
class AbstractFactory

public:
	virtual ~AbstractFactory() 
	virtual AbstractBall *getBall() = 0;
	virtual AbstractShirt *getShirt() = 0;
;

// 具体工厂类BasketballFactory
class BasketballFactory : public AbstractFactory

public:
	BasketballFactory()
	
		printf("BasketballFactory\\n");
	
	AbstractBall *getBall()
	
		printf("Jungle get basketball\\n");
		return new Basketball();
	
	AbstractShirt *getShirt()
	
		printf("Jungle get basketball shirt\\n");
		return new BasketballShirt();
	
;

// 具体工厂类BasketballFactory
class FootballFactory : public AbstractFactory

public:
	FootballFactory()
	
		printf("FootballFactory\\n");
	
	AbstractBall *getBall()
	
		printf("Jungle get football\\n");
		return new Football();
	
	AbstractShirt *getShirt()
	
		printf("Jungle get football shirt\\n");
		return new FootballShirt();
	
;

#endif //__ABSTRACT_FACTORY__

3.4.效果

抽象工厂模式
BasketballFactory
Jungle get basketball
Jungle play Basketball

Jungle get basketball shirt
Jungle wear Basketball Shirt

FootballFactory
Jungle get football
Jungle play Football

Jungle get football shirt
Jungle wear Football Shirt

4.抽象工厂模式总结

抽象工厂模式中,如果需要新增加一个系列的产品,比如足球系列,只需增加一族新的具体产品类(抽象和具体)并提供一个对应的工厂类即可。但是,如果要在已有的产品族里增加另一个产品,比如Jungle打篮球,除了需要篮球和篮球衣外,Jungle还想换双篮球鞋,这时候该怎么办呢?是不是要去修改BasketballFactory呢?由此,Jungle总结了抽象工厂模式的特点:

优点:

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

缺点:

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

适用环境:

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

总结

以上就是今天要讲的内容,本文详细介绍了设计模式中创建型模式之抽象工厂模式(Abstract Factory)介绍和使用,抽象工厂模式(Abstract Factory)设计模式的使用,设计模式提供了大量的方法供我们使用,非常的便捷,我们务必掌握。希望大家多多支持!另外如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。加油啊!

以上是关于设计模式从青铜到王者第七篇:创建型模式之抽象工厂模式(Abstract Factory)的主要内容,如果未能解决你的问题,请参考以下文章

设计模式从青铜到王者第五篇:创建型模式之简单工厂模式( Simple Factory Pattern )

C++从青铜到王者第二十七篇:特殊类设计

设计模式从青铜到王者第八篇:创建型模式之建造者模式(BuilderPattern)

数据结构从青铜到王者第七篇:数据结构之堆

C++从青铜到王者第七篇:STL之string类的初识

Love2d从青铜到王者第七篇:Love2d之对象