Head First 设计模式详解之四:工厂模式

本文详细介绍了工厂方法模式,阐述了如何通过子类决定实例化的类,实现了类的实例化延迟到子类,降低了使用者与具体类的耦合。接着通过饮料店的例子展示了工厂模式的应用,强调依赖抽象而非具体类的设计原则。此外,还探讨了抽象工厂模式,适用于创建相关对象家族的场景,但增加新产品类别时需修改工厂类接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工厂方法模式

定义一个创建对象的接口,但是由子类决定实例化的类是哪一个。工厂方法让类的实例化推迟到子类。

也就是说,我们从基类Base中派生出对象A和B,并且定义Factory,派生出FactoryA和FaceoryB,分别用来生成对象A和B的实例,FactoryA和FactoryB就仿佛是一个工厂,标准地使A和B实例化。使用者将不用关心对象创建,实现使用者与具体类之间的解耦。


举个例子

我们拥有家饮料店,包含各种饮料,牛奶,茶等等。有一个订单类,用来生成我们需要的饮料对象。我们需要根据不同的订单来生成不同的饮料对象。使用工厂模式,可以屏蔽饮料对象的实例化过程,我们只要关心我们的订单类。

定义基类Order,和一个createDrinking接口。不同的饮料订单需要实现createDrinking接口,来完成Drinking对象的实例化操作。

设计原则:依赖抽象,不要依赖具体类。Order和具体的饮料类都应该依赖与Drinking这个抽象类。高层次的Order和Drinking派生出的具体饮料不应该出现依赖关系,它们之间应该通过Drinking这个抽象来联系。

#include <iostream>
#include <string>
using namespace std;

class Drinking{
protected:
    string description;
public:
    virtual string getDescription() {return description;}
};

class Tea : public Drinking{
public:
    Tea() { description = "Tea"; }
};

class Milk : public Drinking{
public:
    Milk() { description = "Milk"; }
};

class Order{
public:
    void show(){
        Drinking* d = createDrinking();
        cout << d -> getDescription() << endl;
        delete d;
    }
    virtual Drinking* createDrinking() = 0;
};

class TeaOrder : public Order{
public:
    Drinking* createDrinking(){ return new Tea();}
};

class MilkOrder: public Order{
public:
    Drinking* createDrinking(){ return new Milk();}
};

int main(){
    TeaOrder o1;
    MilkOrder o2;
    o1.show();
    o2.show();
}

输出结果为:

Tea

Milk

我们在创建订单时,并没有关注Drinking的实例化。工厂模式将对象的实例化封装,使实例化的操作不会出现在代码中,这也符合面向接口编程,而不是面向实现编程的思想。但是,很明显,每当我们增加一个种类时,就需要多新建一个子类。


抽象工厂模式

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

当我们不只有饮料,还有像蛋糕等其他商品时,我们需要创建一个抽象工厂来标准我们要实现的接口。抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。抽象工厂更适用于存在产品家族或者产品集合的情况(我理解是具有成组的多个对象需要实例化)。

我们实现两种订单,一个生成茶和蛋糕,一个生成牛奶和面包。

#include <iostream>
#include <string>
using namespace std;

class Drinking{
protected:
    string description;
public:
    virtual string getDescription() {return description;}
};

class Tea : public Drinking{
public:
    Tea() { description = "Tea"; }
};

class Milk : public Drinking{
public:
    Milk() { description = "Milk"; }
};

class Food{
protected:
    string description;
public:
    virtual string getDescription() {return description;}
};

class Cake : public Food{
public:
    Cake(){ description = "Cake"; }
};

class Bread : public Food{
public:
    Bread(){ description = "Bread"; }
};

class Order{
public:
    void show(){
        Drinking* d = createDrinking();
        Food* f = createFood();
        cout << d -> getDescription() << " ," << f -> getDescription() << endl;
        delete d;
        delete f;
    }
    virtual Drinking* createDrinking() = 0;
    virtual Food* createFood() = 0;
};

class TeaOrder : public Order{
public:
    Drinking* createDrinking(){ return new Tea();}
    Food* createFood(){ return new Cake(); }
};

class MilkOrder: public Order{
public:
    Drinking* createDrinking(){ return new Milk();}
    Food* createFood() { return new Bread(); }
};

int main(){
    TeaOrder o1;
    MilkOrder o2;
    o1.show();
    o2.show();
}

输出结果为:

Tea ,Cake
Milk ,Bread

虽然使用抽象工厂效果强大,帮助我们解耦。但是,当我们需要再添加新的品类时,需要重新修改工厂类的接口,并把所有的具体工厂类重新修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值