工厂类型设计模式
把new
给封装起来,即对象的创建封装起来
一种创建型设计模式
简单工厂
假设场景:用工厂来创建不同的汽车
优点:把对象的创建封装在一个接口函数里面,通过传入不同标识来返回不同的对象。客户不用自己负责创建对象(new),不用了解创建对象的详细过程
实现代码如下:
class Car
{
public:Car(string name) :_name(name){}virtual void show() = 0;
protected:string _name;
};class Bmw : public Car
{
public:Bmw(string name) :Car(name) {}void show(){cout << "获取了一辆宝马汽车:" << _name << endl;}
};class Audi : public Car
{
public:Audi(string name) :Car(name) {}void show(){cout << "获取了一辆奥迪汽车:" << _name << endl;}
};enum CarType
{BMW, AUDI
};
class SimpleFactory
{
public:Car* createCar(CarType ct){switch (ct){case BMW:return new Bmw("X1");case AUDI:return new Audi("Q7");default:cerr << "传入工厂的参数不正确:" << ct << endl;break;}return nullptr;}
};int main()
{// 不好,暴露了对象的创建/*Car* p1 = new Bmw("X1");Car* p2 = new Audi("Q7");*/unique_ptr<SimpleFactory> factory(new SimpleFactory()); // 创建工厂unique_ptr<Car> p1(factory->createCar(BMW));unique_ptr<Car> p2(factory->createCar(AUDI));p1->show();p2->show();return 0;
}
缺点:所有的产品都在一个工厂创建,提供创建对象实例的接口函数不闭合,不满足开闭原则中对修改封闭
工厂方法
优点:设计一个Factory
基类,提供了一个纯虚函数(创建产品),定义派生类(具体产品的工厂)负责创建对应的产品,可以做到不同产品在不同的工厂里创建,能够对现有的工厂以及产品的修改关闭。实现代码如下
// 工厂方法
class Car
{
public:Car(string name) :_name(name) {}virtual void show() = 0;
protected:string _name;
};class Bmw : public Car
{
public:Bmw(string name) :Car(name) {}void show(){cout << "获取了一辆宝马汽车:" << _name << endl;}
};class Audi : public Car
{
public:Audi(string name) :Car(name) {}void show(){cout << "获取了一辆奥迪汽车:" << _name << endl;}
};class Factory
{
public:virtual Car* createCar(string name) = 0;
};class BmwFactory : public Factory
{
public:Car* createCar(string name){return new Bmw(name);}
};
class AudiFactory : public Factory
{
public:Car* createCar(string name){return new Audi(name);}
};int main()
{unique_ptr<Factory> bmwfty(new BmwFactory()); // 创建工厂unique_ptr<Factory> audifty(new AudiFactory()); // 创建工厂unique_ptr<Car> p1(bmwfty->createCar("X6"));unique_ptr<Car> p2(audifty->createCar("A6"));p1->show();p2->show();return 0;
}
工厂方法缺点:实际上,很多产品时有关联关系的,属于一个产品族,不应该放在不同的工厂中创建(如苹果手机和耳机应该在同一个工厂生产)。这样一是不符合实际产品对象的创建逻辑,二是会造成类的数量的膨胀
抽象工厂
优点:将有关联关系的属于一个产品族的所有产品创建接口函数放在一个抽象工厂类AbstractFactory
中,派生类(具体产品的工厂)应该负责创建该产品族的所有产品.
即宝马工厂也生产宝马车灯和宝马座椅,奥迪工厂也生产奥迪车灯和奥迪座椅
实现代码:
class Car
{
public:Car(string name) :_name(name) {}virtual void show() = 0;
protected:string _name;
};class Bmw : public Car
{
public:Bmw(string name) :Car(name) {}void show(){cout << "获取了一辆宝马汽车:" << _name << endl;}
};class Audi : public Car
{
public:Audi(string name) :Car(name) {}void show(){cout << "获取了一辆奥迪汽车:" << _name << endl;}
};// 系列产品
class Light
{
public:virtual void show() = 0;
};class BmwLight : public Light
{
public:void show(){cout << "BMW light!" << endl;}
};
class AudiLight : public Light
{
public:void show(){cout << "Audi light!" << endl;}
};
class AbstractFactory
{
public:virtual Car* createCar(string name) = 0;virtual Light* createCarLight() = 0;
};class BmwFactory : public AbstractFactory
{
public:Car* createCar(string name){return new Bmw(name);}Light* createCarLight(){return new BmwLight();}
};
class AudiFactory : public AbstractFactory
{
public:Car* createCar(string name){return new Audi(name);}Light* createCarLight(){return new AudiLight();}
};int main()
{unique_ptr<AbstractFactory> bmwfty(new BmwFactory()); // 创建工厂unique_ptr<AbstractFactory> audifty(new AudiFactory()); // 创建工厂unique_ptr<Car> p1(bmwfty->createCar("X6"));unique_ptr<Car> p2(audifty->createCar("A6"));unique_ptr<Light> l1(bmwfty->createCarLight());unique_ptr<Light> l2(audifty->createCarLight());p1->show();l1->show();p2->show();l2->show();return 0;
}