一、前言
当软件原有需求有变更或者增加新的需求时,合理的设计模式的应用,能够做到软件设计要求的“开-闭原则”,即对修改关闭,对扩展开放,使软件原有功能修改,新功能扩充非常灵活
合理的设计模式的选择,会使软件设计更加模块化,积极的做到软件设计遵循的根本原则“高内聚,低耦合”
下面简单介绍一下几种工厂模式。
二、工厂模式
工厂模式主要是为创建对象提供了接口。
一般分为三类:简单工厂模式、工厂方法模式、抽象工厂模式。
简单工厂(simple Factory):
是由一个工厂对象决定创建哪一种产品类的实例。我们在实例化对象的时候通常用的是new关键字,但是有了工厂
我们在声明对象的时候就可以用工厂了,用new导致代码不够灵活,用工厂来实例化对象很灵活。
它由三种角色组成:
工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑, 根据逻辑不同,产生具体的工厂产品。
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。
具体产品角色:工厂类所创建的对象就是此角色的实例。
//产品Product基类
class Product
{
public:
Product (string name):_name(name) {}
virtual void show() = 0;//模拟产品对象的一个抽象方法
protected:
string _name;
};
//具体的 产品Product派生类
class ProductA: public Product
{
public:
ProductA (string name):Product (name) {}
void show() {cout << "获取了一个produtA对象:"<<_name<<endl;}
};
class ProductB:public Product
{
public:
ProductB (string name) : Product (name) {}
void show() {cout << "获取了一个produtB对象:"<<_name<<endl;}
};
//创建描述产品类型的枚举和简单工厂类
enum ProductType // 产品类枚举类型定义
{
XIAOMI,
HUAWEI,
};
//简单工厂类
class SimpleFactory
{
public:
通过传入的枚举类型,创建相应的对象,返回所有对象的基类指针
Product* createProduct(ProductType type)
{
switch(type)
{
case XIAOMI :
return new ProductA ("小米手机");
case HUAWEI :
return new ProductB ("华为手机");
}
}
};
int main()
{
//创建简单工厂实例
SimpleFactory sf;
//使用智能指针自动释放堆内存
unique_ptr <Product > p1(sf.createProduct (XIAOMI));
unique_ptr <Product > p2(sf.createProduct (HUAWEI));
p1->show ();
p2->show ();
return 0;
}
使用简单工厂模式能让对象的调用者和对象创建过程分离,当对象调用者需要对象时,直接向工厂请求即可。从而避免了对象的调用者与对象的实现类以硬编码方式耦合,以提高系统的可维护性、可扩展性。但是,它的缺陷就是当产品修改时,工厂类也要做相应修改,违反了开-闭原则。
简单工厂模式适用于业务简单的情况下或者具体产品很少增加的情况。而对于复杂的业务环境可能不太适应了。
这就应该由工厂方法模式来出场了!!
**
工厂方法(Factory Method):
**它是标准的OOP设计模式之一,为每一种产品提供相应的实例工厂进行对象创建。
比如说不通厂家的手机,肯定都有自己的手机生产工厂,XIAOMI和HUAWEI两种手机都有自己的工厂在生产。
// 产品类型
class Product
{
public:
Product(string name) :_name(name) {}
// 模拟产品对象的一个抽象方法
virtual void show() = 0;
protected:
string _name;
};
// 产品实体类型定义
class ProductA : public Product
{
public:
ProductA(string name) :Product(name){}
void show() { cout << "获取了一个使用老外高通芯片的手机:" << _name << endl; }
};
// 产品实体类型定义
class ProductB : public Product
{
public:
ProductB(string name) :Product(name) {}
void show() { cout << "获取了一个使用自研麒麟芯片的手机:" << _name << endl;
}
};
// 工厂基类
class Factory
{
public:
virtual Product* createProduct() = 0;
};
//生产小米手机的工厂
class XiaomiFactory : public Factory
{
public:
Product * createProduct ()
{
//小米手机工厂肯定生产小米手机
return new ProductA ("小米手机");
}
};
//生产华为手机的工厂
class HuaweiFactory:public Factory
{
public:
Product* createProduct()
{
// 华为工厂肯定生产华为手机
return new ProductB("华为手机");
}
};
int main()
{
// 使用智能指针自动释放堆内存
// 创建具体的工厂
unique_ptr<Factory> f1(new XiaomiFactory);
unique_ptr<Factory> f2(new HuaweiFactory);
// 通过工厂方法创建产品
unique_ptr<Product> p1(f1->createProduct());
unique_ptr<Product> p2(f2->createProduct());
p1->show();
p2->show();
return 0;
}
通过产生具体的工厂创建具体的产品,做到了在扩充新产品时,能够达到软件设计的“开-闭”原则.
会发现一个问题,就是每一个实例工厂负责生产一个实例产品,也就是一个产品对应一个工厂,一个工厂对应一个产品,那么小米不仅仅生产手机,还生产耳机,智能手环,智能插座等等相关的小米产品簇,不可能给这每一个产品都创建一个工厂类,那样的话代码中的类就太多了,不好维护,而且也不符合实际情况。
实际上小米或者华为的工厂里面,有相关联的产品簇都是在一个工厂完成创建的;BMW或者Audi汽车制造工厂除了生产汽车,生产线上也有可能生产轮胎,或者其它的汽车附属产品。
所以对于包含产品簇这么一类实体关系的设计,就需要使用Abstract Factory抽象工厂了!!
抽象工厂(Abstract Factory):
抽象工厂其实就是解决产品簇的产品类设计的。
// 产品簇手机类型
class ProductA
{
public:
ProductA(string name) :_name(name) {}
// 模拟产品对象的一个抽象方法
virtual void show() = 0;
protected:
string _name;
};
// 产品实体类型定义
class XiaomiPhone : public ProductA
{
public:
XiaomiPhone(string name) :ProductA(name){}
void show() { cout << "获取了一个小米手机:" << _name << endl; }
};
// 产品实体类型定义
class HuaweiPhone : public ProductA
{
public:
HuaweiPhone(string name) :ProductA(name) {}
void show() { cout << "获取了一个华为手机:" << _name << endl;
}
};
// 产品簇智能手环类型
class ProductB
{
public:
ProductB(string name) :_name(name) {}
// 模拟产品对象的一个抽象方法
virtual void show() = 0;
protected:
string _name;
};
// 产品实体类型定义
class XiaomiCircle : public ProductB
{
public:
XiaomiCircle(string name) :ProductB(name) {}
void show() { cout << "获取了一个小米智能手环设备:" << _name << endl; }
};
// 产品实体类型定义
class HuaweiCircle : public ProductB
{
public:
HuaweiCircle(string name) :ProductB(name) {}
void show() {
cout << "获取了一个华为智能手环设备:" << _name << endl;
}
};
// 抽象工厂,创建通过一个产品簇的设备产品
class AbstractFactory
{
public:
// 工厂里面创建手机的纯虚函数接口
virtual ProductA* createPhone() = 0;
// 工厂里面创建智能手环的纯虚函数接口
virtual ProductB* createSmartCircle() = 0;
};
// 生产小米产品簇的工厂
class XiaomiFactory : public AbstractFactory
{
public:
ProductA* createPhone()
{
// 小米工厂肯定生产小米手机
return new XiaomiPhone("小米x9");
}
ProductB* createSmartCircle()
{
// 小米工厂肯定生产小米智能手环
return new XiaomiCircle("小米智能手环2代时尚版");
}
};
// 生产华为产品簇的工厂
class HuaweiFactory : public AbstractFactory
{
public:
ProductA* createPhone()
{
// 华为工厂肯定生产华为手机
return new HuaweiPhone("华为荣耀7x");
}
ProductB* createSmartCircle()
{
// 华为工厂肯定生产华为智能手环
return new HuaweiCircle("华为智能手环B3青春版");
}
};
int main()
{
// 使用智能指针自动释放堆内存
// 创建具体的工厂
unique_ptr<AbstractFactory> f1(new XiaomiFactory);
unique_ptr<AbstractFactory> f2(new HuaweiFactory);
// 通过工厂方法创建手机产品
unique_ptr<ProductA> p1(f1->createPhone());
unique_ptr<ProductA> p2(f2->createPhone());
p1->show();
p2->show();
// 通过工厂方法创建智能手环产品
unique_ptr<ProductB> p3(f1->createSmartCircle());
unique_ptr<ProductB> p4(f2->createSmartCircle());
p3->show();
p4->show();
return 0;
}
总结:三个工厂都是各有利弊,简单工厂违反了最基本的原则,工厂方法与抽象工厂完美的解决了简单工厂的弊端!工厂方法的工厂个数过多,导致系统庞大,抽象工厂增加新的产品族很方便。