本文适合新手和小白
目录
1、Absstract Factrory
(1)意图
(2)结构
(3)适用性
2、看类图写码
(1)利用泛化关系
(2)利用c++多态的特点
(3)利用依赖关系
(4)UML图流程理解
(5)代入生活
3、完成代码
1、Absstract Factrory
(1)意图
根据《软件设计师教程》第五版第379页概念介绍,抽象工厂是一个提供一个创建系列相关或相互依赖的接口,而无需指定它们具体的类。
(2)结构
抽象工厂模式结构图
图片来源:互联网,本图和教科书上的几乎一摸一样故选用
其中 :AbstractFactory声明一个创建抽象类产品对象的接口。
ConcreteFactory实现创建具体产品对象的操作。
AbstractProdcut为一类产品对象声明一个接口。
Client仅使用由AbstractProdcut和AbstractFactory类声明的接口。
(3)适用性
一个系统要独立与它的产品的创建、组合、表示时。
一个系统要有多个产品系列中的一个来配置时。
当要强调一个系列相关的产品对象的设计以便进行联合使用时。
当提供一个产品类库,只想显示它们的接口而不是实现时。
2、看类图写码
作为一个非专业出生的编程爱好者,现在我们一起根据UML类图来编写代码
(1)利用泛化关系
根据教材366页的解释。泛化是一种特殊/一般的关系,特殊元素(子元素)的对象可替代一般元的对象。用这种方法子元素共享了父元素的结构和行为。我们可以理解为父类和子类利用多态特诊完成我们需要的操作,本例子中ConcreteFactory1与AbstractFactory类就是子与父的关系,中间的箭头由子类指向父类。
(2)利用c++多态的特点
根据C++多态的特征,往往还采用虚函数和this指针相结合,历年软考也常常利用这个知识点出考题,本UML一共有6组泛化关系它们分别是(大家可以对照教材仔细看):
ProductA1、AbsreactProductA
ProductA2、AbsreactProductA
ProductB1、AbsreactProductB
ProductB2、AbsreactProductB
ConcreteFactory1、AbstractFactory
ConcreteFactory2、AbsreactFactory
那么根据该UML图的描述、命名、属性、操作,我们先不管到底要干啥,我们先根据UML的的给出已知条件把,这层泛化关系写出来,部分泛化关系代码如下:
class AbstractProductA{
public:
virtual void productA()=0;
virtual ~AbstractProductA(){};
};//抽象产品A类
class ProductA1:public AbstractProductA{//具体的A类产品
public:
void productA(){
};
virtual ~ProductA1(){
};
};
class AbstractFactory{
public:
virtual void *CreateProductA()=0;
virtual void *CreateProductB()=0;
virtual ~AbstractFactory(){};
};
class ConcreteFactory1:public AbstractFactory{
public:
void *CreateProductA(){
};
void *CreateProductB(){
};
~ConcreteFactory1(){};
};
(3)利用依赖关系
依赖关系在UML图中时带箭头的虚线,体现了类之间的弱作用关系,是一种临时性的使用关系,在代码中的表现为,简单理解就是类A使用到了类B,类B作为参数被类A在某个方法中使用,类A的一些方法逻辑中调用了类B的方法或变量等等。主要有形式有如下特征:
1.A类的操作需要B类的参数;
2.A类的操作返回B类;
3.A类的操作实现中使用B类提供的对象
在本UML图中一共有2组依赖关系它们分别是:
Concretefactory1指向ProductA1和ProductA2,既ProductA1和ProductA2被Concretefactory1使用,根据对UML图的理解,我们需要实现A类的操作返回B类,既在Concretefactory1返回ProductA1和ProductA2。
Concretefactory2指向ProductB1和ProductB2,既ProductB1和ProductB2被Concretefactory2使用,根据对UML图的理解,我们需要实现A类的操作返回B类,既在Concretefactory2中返回ProductB1和ProductB2。
根据这层关系我们可以在泛化关系构成的代码上进行如下补充和调整,部分代码如下:
class ConcreteFactory1:public AbstractFactory{
public:
AbstractProductA* CreateProductA(){//根据UML图的理解一定是返还一个(抽象)产品
//所以将void换成AbstractProductA*
return new ProductA1;//根据UML图的理解一定是返回一个具体的产品
//具体产品为ProductA1
};
AbstractProductB *CreateProductB(){//跟上面一样不在复述
return new ProductB1;
};
(4)UML图流程理解
根据上述UML图及部分的代码的构成,我们可以将代码整体流程做出如下理解:
第一步
Client中通过 AbstractFactory这个抽象父类作为接口,通过多态性使用子类ConcreteFactory1。
第二步
通过ConcreteFactory1中CreateProdctA和CreateProdctB实现具体产品 ProductA1和 ProductB1的生产
(5)代入生活
为了方便理解,我们可以将复杂的UML图代入日常生活, AbstractFactory我们把他理解一个服装生产的业界杠把子,他有2个专门的工厂,一个生产牛仔裤一个生产T恤其中:
ConcreteFactory1专门生产牛仔裤的工厂,他产品是女式牛仔裤(ProductA1)和男式牛仔裤(ProductB1)
ConcreteFactory2专门生产T恤,他的产品是女式T恤(ProductA2)和男式T恤(ProductB2)
AbstractProdcutA为女式服饰,它们包括女式牛仔裤(ProductA1)和女式T恤(ProductA2)
AbstractProdcutB为男式服饰,它们包括男式牛仔裤(ProductB1)和男式T恤(ProductB2)
最终实现方式:
通过 AbstractFactory这个服装生产界的业界面扛把子,向ConcreteFactory1专门生产牛仔裤的工厂下订单,让他为我们生产女式牛仔裤(ProductA1)和男式牛仔裤(ProductB1)
通过 AbstractFactory服装生产界的业界面扛把子,向ConcreteFactory2专门生产T恤的工厂下订单,让他为我们生产男式牛仔裤(ProductB1)和男式T恤(ProductB2)
3、完成代码
#include
using namespace std;
class AbstractProductA{
public:
virtual void productA()=0;
virtual ~AbstractProductA(){};
};//抽象产品A类,女式
class AbstractProductB{
public:
virtual void productB()=0;
virtual ~AbstractProductB(){};
};//抽象产品B类,男式
class ProductA1:public AbstractProductA{//女式牛仔裤
public:
void productA(){
cout<<"女式牛仔裤"<CreateProductA();//计划生产女牛仔裤
lady_jeans->productA();//生产女式女仔裤
AbstractProductB *jeans=a->CreateProductB();//计划生产男牛仔裤
jeans->productB();//生产男式牛仔裤
}
void create_tshirt(){
AbstractFactory *b=new ConcreteFactory2();//体恤如上
AbstractProductA *lady_t_shirt=b->CreateProductA();
lady_t_shirt->productA();//女式T恤
AbstractProductB *t_shirt=b->CreateProductB();
t_shirt->productB();//男式T恤
}
~Client(){
if (a!=NULL){
delete a;
a=NULL;
}
if (b!=NULL) {
delete b;
b=NULL;
}
}
AbstractFactory *a;
AbstractFactory *b;
AbstractProductA *lady_jeans;
AbstractProductA *lady_t_shirt;
AbstractProductB *jeans;
AbstractProductB *t_shirt;
};
int main(){
Client *a;
a->create_jeans();
a->create_tshirt();
return 0;
}
根据UML图的要求Client仅仅使用AbstractFactory和AbstractProdcut,所以相关代码实现我特意写一个Client类,个人觉得可读性上反而比较差,个人感觉可以直接在main函数中直接写会比较接地气。
运行结果:
希望对大家学习有帮助,若有错误请指出



