C++设计模式Learning:工厂方法

前言

我们知道,设计模式的终极目标是高内聚,低耦合,好的软件代码必然离不开好的设计。最近在学习设计模式这块的内容,参考的书籍是程杰的《大话设计模式》,这本书对于初学者来说比较友好,易上手,博客里的内容是参考本书以及网络资源整理的。

博客更新基本上是边学边写的过程,写这个专题一是为了作为自己的知识备忘,二是希望能给正在学习设计模式的童鞋一些参考,博客中内容有纰漏或错误之处,还请指出,谢谢。

基本定义

工厂方法模式,属于创建型模式。工厂方法模式定义了一个用于创建工厂对象的公共接口,让子类决定实例化哪一个类。这样使得类实例化(具体产品的创建)延迟到工厂子类中。

UML图

工厂方式模式包含以下几类角色:

AbstractFactory:抽象工厂角色(接口)。提供创建产品的接口(抽象方法)CreateProduct,由具体工厂角色实现。

ConcreteFactory:具体工厂角色。用于实现抽象工厂的抽象方法,完成具体产品的创建。

Product:抽象产品角色,是所有具体产品的父类,定义了产品的规范,主要特性和功能接口等。

ConcreteProduct:具体产品角色,实现抽象产品类中提供的接口,具体产品由具体工厂来创建。

工厂方法模式实例

场景:生活中有很多人都想学雷锋做好事,比如学生、志愿者、工人等。学雷锋做好事的内容主要包括扫地、买米、洗衣等。

这里可以抽象出一个雷锋制造工厂的概念,还可以抽象出一个雷锋类,行使雷锋做好事的内容,下面展开。

UML图

代码实现

1. 雷锋类:提供雷锋做好事行为的接口。

//LeiFeng类

class LeiFeng {
public:
    virtual void Sweep(void) = 0;
    virtual void BuyRice(void) = 0;
    virtual void Wash(void) = 0;
};

2. 学雷锋的大学生类:

class Undergraduate : public LeiFeng {
public:
    virtual void Sweep(void)
    {
        std::cout << "Undergraduate.Sweep!!" << std::endl;
    }

    virtual void BuyRice(void)
    {
        std::cout << "Undergraduate.BuyRice!!" << std::endl;
    }

    virtual void Wash(void)
    {
        std::cout << "Undergraduate.Wash!!" << std::endl;
    }
};

3. 学雷锋的志愿者类:

class Volunteer: public LeiFeng {
public:
    virtual void Sweep(void)
    {
        std::cout << "Volunteer.Sweep!!" << std::endl;
    }

    virtual void BuyRice(void)
    {
        std::cout << "Volunteer.BuyRice!!" << std::endl;
    }

    virtual void Wash(void)
    {
        std::cout << "Volunteer.Wash!!" << std::endl;
    }
};

4. 学雷锋的工人类:

class Worker: public LeiFeng {
public:
    virtual void Sweep(void)
    {
        std::cout << "Worker.Sweep!!" << std::endl;
    }

    virtual void BuyRice(void)
    {
        std::cout << "Worker.BuyRice!!" << std::endl;
    }

    virtual void Wash(void)
    {
        std::cout << "Worker.Wash!!" << std::endl;
    }
};

5. 雷锋工厂

class LeiFengFactory {
public:
    virtual LeiFeng* CreateLeiFeng(void) = 0;
};

6. 学雷锋的大学生工厂

class UndergraduateFactory : public LeiFengFactory {
public:
    LeiFeng* CreateLeiFeng(void)
    {
        return new Undergraduate();
    }
};

7. 学雷锋的志愿者工厂

class VolunteerFactory : public LeiFengFactory {
public:
    LeiFeng* CreateLeiFeng(void)
    {
        return new Volunteer();
    }
};

8. 学雷锋的工人工厂

class WorkerFactory : public LeiFengFactory {
public:
    LeiFeng* CreateLeiFeng(void)
    {
        return new Worker();
    }
};

7. 客户端测试代码

int main(int argc, char* argv[])
{
    LeiFengFactory *LeiFengFac = new UndergraduateFactory();
    LeiFeng* one = LeiFengFac->CreateLeiFeng();
    one->Sweep();
    one->Wash();
    one->BuyRice();
    LeiFeng* two = LeiFengFac->CreateLeiFeng();
    two->Sweep();
    two->Wash();
    two->BuyRice();
    return 0;
}

优缺点和使用场景

优点:

1.灵活性增强,添加新产品时,只需添加对应的工厂类,无需修改现有代码,符合开闭原则。

2. 用户无需知道产品的具体创建过程,只需知道产品工厂类名。

缺点:

1. 类数量可能较多。

2. 每增加新产品需要增加具体产品类和具体工厂类,增加系统复杂度。

使用场景:

对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化具体工厂,生产出具体的产品。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值