前言:简单工厂模式到工厂模式的更新,我只用了一天时间,一是因为确实比较简单,二是那两天工作不是很忙。(嘻嘻)。抽象工厂模式确是三种工厂模式中最难理解的,其实我也是现学现卖的,大家一起进步吧。
写这篇博客之前我也看过网上有关抽象工厂模式的其他帖子,发现举的栗子都是不太让人理解。简单工厂模式和工厂模式都是拿计算器举栗子,但是抽象工厂模式感觉不太适合计算器的栗子,本文的代码乃本人所写,自认为比较形象的介绍了抽象工厂模式。
还是先说一下定义:
抽象工厂模式:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体的类。
不知道其他人看完这个定义什么感觉,反正我是一脸懵逼,这讲的是什么玩意???当我弄懂抽象工厂模式回过头再来看这个定义才算理解,别着急,慢慢来。
#include <iostream>
using namespace std;
class Phone //抽象手机产品基类
{
protected:
int prise;
int num;
public:
Phone():prise(0),num(0){}//初始化基类成员变量
void set(int A, int B)//见注1
{
prise = A;
num = B;
}
virtual void Show() = 0;//见注2
};
class HuaWeiPhone :public Phone//具体手机产品
{
public:
void Show()
{
cout << "生产"<< num <<"台华为手机结束,"<<"成本总共"<<num* prise <<"元。" << endl;
}
};
class HonorPhone :public Phone
{
public:
void Show()
{
cout << "生产"<< num <<"台荣耀手机结束, "<< "成本总共" << num * prise << "元。" << endl;
}
};
class Book
{
protected:
int prise;
int num;
public:
Book() :prise(0), num(0){}//初始化基类变量
void set(int A, int B)
{
prise = A;
num = B;
}
virtual void Show() = 0;
};
class HuaWeiBook :public Book
{
public:
void Show()
{
cout << "生产"<< num <<"台华为平板结束,"<< "成本总共" << num * prise << "元。" << endl;
}
};
class HonorBook :public Book
{
public:
void Show()
{
cout << "生产"<< num<<"台荣耀平板结束,"<< "成本总共" << num * prise << "元。" << endl;
}
};
class AbstractFactory
{
public:
virtual Phone * CreatPhone() = 0;//见注3
virtual Book * CreatBook() = 0;
};
class HuaWeiFactory :public AbstractFactory//具体工厂,调用不同实现,可以生产不同的产品
{
public:
Phone * CreatPhone()
{
return new HuaWeiPhone;
}
Book * CreatBook()
{
return new HuaWeiBook;
}
};
class HonorFactory :public AbstractFactory
{
public:
Phone * CreatPhone()
{
return new HonorPhone;
}
Book * CreatBook()
{
return new HonorBook;
}
};
int main()
{
HuaWeiFactory F1;//见注4
HonorFactory F2;
int num1, num2, num3, num4;
cout << "华为手机的单价是 3000 元,华为平板的单价是 5000 元" << endl;
cout << "你想要生产多少华为手机和华为平板 ?" << endl;
cin >> num1 >> num2;
Phone *p1=F1.CreatPhone();//见注5
p1->set(3000, num1);//传入类参数
p1->Show();
cout << endl;
Book *p2 = F1.CreatBook();
p2->set(5000, num2);
p2->Show();
cout << endl;
cout << "荣耀手机的单价是 2000 元,荣耀平板的单价是 4000 元" << endl;
cout << "你想要生产多少荣耀手机和荣耀平板 ?" << endl;
cin >> num3 >> num4;
Phone *p3 = F2.CreatPhone();
p3->set(2000, num3);
p3->Show();
cout << endl;
Book *p4 = F2.CreatBook();
p4->set(4000, num4);
p4->Show();
cout << endl;
delete p1;delete p2;delete p3;delete p4;//见注6
return 0;
}
运行结果:
几点解释,大佬绕行。
注1:在Phone基类中,此set函数却不是虚函数,在基类中就已经给出了实现,这样做是因为在所有的派生类中,此函数的是实现相同的功能,都是传函数参数给类使用。子类就不需要定义参数直接使用基类的参数即可,因为是单线程,所以这样实现可以。如果是多线程的情况下,基类中的变量会变化,导致子类中其他使用参数的函数会出现错乱。
注2:因为每个子类都不相同,此函数必须要定义为虚函数,在基类中不给于具体的实现,由每个具体的子类去实现。
注3:此类是抽象工厂类。virtual Phone * CreatPhone() = 0,注意此方法的返回类型是指向抽象类Phone的指针,而Phone抽象类有两个具体的实现,HuaWeiPhone、HonorPhone类,这就是定义中创建一个相互依赖的接口,没有指定具体的类。
注4:定义一个具体工厂F1,这使用的是局部变量,数据存在栈中,这块内存随用随扔。
注5:定义一个抽象产品p1,这里要注意,p1的来源是工厂创建的,在创建的过程中使用了new,所以这块内存是存在堆中的,这块内存使用完毕必须释放,在华为公司如果这样写代码,会违反华为的“飞检十条”。
注6:和注5相呼应,删除之前申请的内存。
抽象工厂模式的优缺点:
它让具体的创建实实例过程和客户端分离,客户端通过抽象接口来操纵实例。但是如果我们要新增加一个产品,就要更改AbstractFactory、具体的工厂,可以说很麻烦了。