跳至主要內容

简单工厂、工厂方法、抽象工厂

张威大约 6 分钟c/c++设计模式

简单工厂、工厂方法、抽象工厂

属于创建型设计模式

简单工厂(Simple Factory)

  • 简单工厂(Simple Factory) 不属于标准的OOP设计模式中的一项,工厂方法和抽象工厂是属于标准的23种设计模式的;

  • 在编写大型C++软件的时候,代码里面会出现每次创建对象的时候,都需要通过new 类名称的方式来生成对象,这样一来,用户,暂且不管记不记得住,这样的设计使得代码很难维护,,不符合我们软件设计的思想,Simple Factory就是在这样的需求下诞生的。

  • 工厂方法主要是封装了对象的创建!

1.1、采用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;
    }
};

int main() {
    Car *p1 = new Bmw("X1");
    Car *p2 = new Audi("A6");
}

缺点:

1.2、采用简单工厂

  • 从上面的UML类图可以看出,所有对象的创建不再通过new 类名称的方式进行了,而是把对象的创建都封装在了SimpleFactory类的createProduct方法当中
  • 通过传入一个事先设计好的枚举类型,然后返回一个对应的对象,既解耦了对象的创建,还不用再记忆那么多的类名。

实现

将类名设为首字母大写:(防止和枚举的名称重复)

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("A6");
                
            default:
                cerr << "传入工厂的参数不正确" << ct << endkl;
                break;
        }
        return nullptr;
    }
};

int main() {
    //Car* p1 = new Bmw("X1");
    //Car* p2 = new Audi("A6");
    
    SimpleFactory * factory = new SimpleFactory();
    Car* p1 = factory->createCar(BMW);
    Car* p2 = factory->createCar(AUDI);
    
    p1->show();
    p2->show();
    
    delete p1;
    delete p2;
    delete p3;
    
    return 0;
}

也可以在工厂方法中使用管理:

#include <memory>

int main() {
    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;
}

缺点:把所有对象的创建都封装在了一个SimpleFactory类的createCar函数中,根据传入的参数,选择产生不同的对象,很明显,,所以这样的设计不能算完美。

2、工厂方法(Factory Method)

2.1、类图

Factory Method工厂方法是标准的OOP设计模式之一,主要解决了上面使用简单工厂遇到的问题。

工厂方法为每一种产品提供相应的实例工厂进行对象创建,更符合实际的面向对象设计,比如说不同厂家的汽车,肯定都有自己的汽车生产工厂,BMW和Audi两种汽车都有自己的工厂在生产。

先看看工厂方法的UML类设计图如下:

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<Facory> bmwfty(new BMWFactroy());
    unique_ptr<Facory> audifty(new AudiFactroy());
    unique_ptr<Car> p1(bmwfty->createCar("X6"));
    unique_ptr<Car> p2(audifty->createCar("A8"));
    
    p1->show();
    p2->show();
    
    return 0;
}

优点:符合软件设计的开-闭原则

缺点:

  • 就是每一个实例工厂负责生产一个实例产品,也就是,那么小米不仅仅生产手机,还生产耳机,智能手环,智能插座等等相关的小米产品簇;

  • ,而且也不符合实际情况。
  • 实际上小米或者华为的工厂里面,有相关联的产品簇都是在一个工厂完成创建的;BMW或者Audi汽车制造工厂除了生产汽车,生产线上也有可能生产轮胎,或者其它的汽车附属产品。

所以对于包含产品簇这么一类实体关系的设计,就需要使用Abstract Factory抽象工厂了,你也可以把上面的工厂方法看作只生产一种产品的抽象工厂,本质是相同的

抽象工厂(Abstract Factory)

抽象工厂其实就是解决设计的

  • 看上面抽象工厂的UML类设计图,ProductA和ProductB就是一个产品簇。
//系列产品1
class Car {
public:
    Car(string name) : _name(name) {}
    virtual void show() = 0;
    
protected:
    string _name;
};

class Bmw : public Car {
public:
    Bmw(string name) _name(name) {}
   	void show() {
        cout << "获取了一辆宝马汽车:" << _name << endl;
    }
};

class Audi : public Car {
public:
    Audi(string name) : Car(name) {}
    void show() {
        cout << "获取了一辆奥迪汽车:" << _name << endl;
    }
};

//系列产品2
class Light {
public:
    virtual void show() = 0;
};

class BmwLight : public Light {
public:
    void show() {
        cout << "BMW Light!" << endl;
    }
};

class AudiLight : public Light {
    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 AudiCarLight();
    }
};

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("A8"));
    unique_ptr<Light> l1(bmdfty->createCarLight());
    unique_ptr<light> l2(auditfy->createCarLight());
    
    p1->show();
    l1->show();
    
    p2->show();
    l2->show();
    return 0;
}

优点:使得,不用每个产品类建一个工厂

缺点:(抽象类必须重写!)!!!

简单工厂,工厂方法,抽象工厂对比

image-20240428143246759
image-20240428143246759