设计模式之工厂模式

一:工厂模式

将实例化具体类的过程交给工厂,你只用告诉它你需要什么样的类型就好了。

比如下面这段代码:

Fruit createFruit(string name) {
    Fruit fruit;

    --------------------------------
    if(name == "Apple") {
        fruit = new Apple();
    }
    else if(name == "Banana") {
        fruit = new Banana();
    }
    else if(name == "peach") {
        fruit = peach();
    }
    ---------------------------------
    fruit.cut();      //将水果切块
    fruit.box();      //将水果装盒

    return fruit;
}

如果我将上面代码片段中两条横线之间的代码实现为另一个方法叫FruitFactory,如下所示:

Fruit FruitFactory(string name) {
    Fruit fruit;

    if(name == "Apple") {
        fruit = new Apple();
    }
    else if(name == "Banana") {
        fruit = new Banana();
    }
    else if(name == "peach") {
        fruit = peach();
    }
    return fruit;
}

那原来的类就变成了下面这个样子:

Fruit createFruit(string name) {
    Fruit fruit;

    fruit = FruitFactory("Apple");  //创建水果
    fruit.cut();                    //将水果切块
    fruit.box();                    //将水果装盒

    return fruit;
}

好,如果上面的你都理解了,那你就算学会工厂模式了,据说它更像一种编程习惯。

二:为什么要把上面的代码分离出去?

  • 将创建对象的代码集中在一个对象或者方法中,可以避免代码的重复,并且更加方便对象的维护,如果以后别的文件中也需要创建对象,只用调用FruitFactory方法就行了。
  • 分离实现了解耦,现在水果的创建和水果其它操作(切、装盒)是分开的,假设我们要加新品种的水果,那只用在FruitFactory中加入相应代码就行了。

三:我们开一家水果店吧!

这里写图片描述

我们将上面的FruitFactory抽象成了现在的水果店基类。因为可能不同的水果店有不同的水果,比如北京的水果店上海的水果店可能供应的品种是不同的,那它们各自的实现方法createFruit()中不应该都包含所有水果的实现方法。现在我们要订水果怎么办呢?

FruitStore *bjFruitStore = new BJFruitStore(); //新建一个北京的水果店,不要惊奇呀,你都用工厂模式了,开个水果店不很正常吗。
bjFruitStore->orderFruit("Apple"); //预定一个北京水果店的苹果。

四:具体的实现

这次是c++实现:

Fruit.h

#include<iostream>
#include<string>

#ifndef _FRUIT_H
#define _FRUIT_H

class Fruit {
public:
    void cut() {
        std::cout << "Fruit is cutt" << std::endl;
    }
    void box() {
        std::cout << "Fruit is box" << std::endl;
    }
    std::string name;
};

#endif

Apple.h

#include<iostream>
#include<string>
#include"Fruit.h"

#ifndef _APPLE_H
#define _APPLE_H

class Apple: public Fruit{
public:
    Apple(){
        name = "Apple";
    }

};

#endif

Banana.h

#include"Fruit.h"

#ifndef _BANANA_H
#define _BANANA_H

class Banana:public Fruit {
public:
    Banana(){
        name = "Banana";
    }
};

#endif

FruitStore.h

#include<iostream>
#include<string>
#include"Fruit.h"

#ifndef _FRUITSTORE_H
#define _FRUITSTORE_H

class FruitStore {
public:
    void orderFruit(std::string name) {
        Fruit *fruit;
        fruit = createFruit(name);
        fruit->cut();
        fruit->box();
    }
    virtual Fruit *createFruit(std::string name) = 0; //纯虚函数
private:

};


#endif

BJFruitStore.h

#include<iostream>
#include<string>
#include"FruitStore.h"
#include"Apple.h"
#include"Banana.h"


#ifndef _BJFRUITSTORE_H
#define _BJFRUITSTORE_H

class BJFruitStore: public FruitStore {
public:
    Fruit* createFruit(std::string name){
        if(name == "Apple") {
            std::cout << "Created Apple" << std::endl;
            return new Apple();
        }else if(name == "Banana") {
            std::cout << "Created Banana" << std::endl;
            return new Banana();
        }
    }

};

#endif

main.h

#include<iostream>
#include"FruitStore.h"
#include"BJFruitStore.h"

int main(int argc,char *argv[])
{
    FruitStore *fs = new BJFruitStore();
    fs->orderFruit(std::string("Apple"));
    std::cout << "After a While..." <<std::endl;
    fs->orderFruit(std::string("Banana"));
    return 0;
}

这里写图片描述

五:总结

  • 尽量让类派生自接口,而不是具体类,使用组合而不是继承。
  • 避免派生类覆盖基类中的方法,如果需要覆盖,那这个方法就抽象的不合理。
  • 最好将new交给工厂去管理。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨博东的博客

请我喝瓶可乐鼓励下~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值