Halibaba

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

1. 场景

    假设有如下的场景:

    卖pizza的, 可以有很多种pizza(CheesePizza, GreekPizza, PepperoniPizza),我们该如何处理它呢,当然我们可以声明一个类,类中创建每一个种类的pizza。但是这样有什么问题吗?我们没有把需要改变的部分剥离出来。软件设计的一个原则就是“是易于扩充而不是修改”,另一个是“对接口编程而不是对实现编程”。

    这里就轮到工厂模式出手了。 工厂模式有三种:

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

2. 简单工厂模式

    1.1 Uml

image

1.2 源代码

class Pizza 
{ 
 public: 
     Pizza(){}; 
    virtual ~Pizza(){};

    virtual void MakePizza() = 0; 
};

 class CheesePizza : public Pizza 
{ 
 public: 
    CheesePizza(){}; 
    ~CheesePizza(){};

 void MakePizza() 
{ 
    cout << "make cheese pizza" <<endl; 
} 
};

class GreekPizza : public Pizza 
{ 
public: 
    GreekPizza(){}; 
    ~GreekPizza(){};

    void MakePizza() 
    { 
        cout << "make greek pizza" <<endl; 
    }

};

class PepperoniPizza : public Pizza 
{ 
public: 
    PepperoniPizza(){}; 
    ~PepperoniPizza(){};

    void MakePizza() 
    { 
        cout << "make peperoni pizza" <<endl; 
    }

};

enum PIZZA_TYPE 
{ 
    PIZZA_TYPE_CHEESE = 0, 
    PIZZA_TYPE_GREEK, 
    PIZZA_TYPE_PEPPERONI 
};

class PizzaFactory 
{ 
public: 
    PizzaFactory(){}; 
    ~PizzaFactory(){};

    static shared_ptr<Pizza> createPizza(PIZZA_TYPE pizzaType) 
    { 
        switch (pizzaType) 
        { 
        case PIZZA_TYPE_CHEESE: 
            return shared_ptr<Pizza>(new CheesePizza()); 
        case PIZZA_TYPE_GREEK: 
            return shared_ptr<Pizza>(new GreekPizza()); 
        case PIZZA_TYPE_PEPPERONI: 
            return shared_ptr<Pizza>(new PepperoniPizza()); 
        default: 
            return shared_ptr<Pizza>(new PepperoniPizza()); 
        } 
    } 
};

测试代码

int _tmain(int argc, _TCHAR* argv[]) 
{

    shared_ptr<Pizza> cheesePizza = PizzaFactory::createPizza(PIZZA_TYPE_CHEESE); 
    shared_ptr<Pizza> greekPizza = PizzaFactory::createPizza(PIZZA_TYPE_GREEK); 
    shared_ptr<Pizza> pepperoniPizza = PizzaFactory::createPizza(PIZZA_TYPE_PEPPERONI);

    cheesePizza->MakePizza(); 
    greekPizza->MakePizza(); 
    pepperoniPizza->MakePizza(); 
    return 0; 
}

这样写好什么好处呢?

  1. .静态工厂方法统一管理对象的创建
  2. 静态工厂方法推迟了产品的实例化。

这样写的缺点是什么呢?

  缺点就是在增加新的类型时,需要修改工厂类。这违反了开放封闭原则:软件实体(类、模块、函数)可以扩展,但是不可修改。于是需要更高级的工厂方法模式。

2. 工厂方法模式

    工厂方法模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

    当然从代码的角度就是其实就是把 PizzaFactory 抽象出来,用子类来实现。

class PizzaFactory 
{ 
public: 
    PizzaFactory(){}; 
    ~PizzaFactory(){};

    virtual Pizza* createPizza()  = 0;
};

class PizzaFactoryCheese : public PizzaFactory
{
public:
     CheesePizza*    createPizza() { return new CheesePizza; }
}

class PizzaFactoryGreek : public PizzaFactory
{
public:
     GreekPizza*    createPizza() { return new GreekPizza; }
}

   注意:由于此时PizzaFactory的createPizza()为虚函数,因此不能使用static修饰符。

   工厂方法模式也有缺点,每增加一种产品,就需要增加一个对象的工厂。显然,相比简单工厂模式,工厂方法模式需要更多的类定义。

   至此,貌似有简单工厂模式和工厂方法模式所有问题都可以应付了,但是,如果生意扩大了,除了Pizza又做Hamburger了,怎么办? 于是抽象工厂模式出现了。

3. 抽象工厂

    抽象工厂和工厂方法的主要区别是工厂方法使用继承来创建对象,而抽象工厂是使用组合。

image 

例子代码如下:

class Burger
{ 
 public: 
     Burger(){}; 
    virtual ~Burger(){};

    virtual void MakeBurger() = 0; 
};

 class KfcBurger : public Burger
{ 
 public: 
    KfcBurger (){}; 
    ~KfcBurger (){};

 void MakeBurger() 
{ 
    cout << "make KFC Burget" <<endl; 
} 
};

 class McdBurger : public Burger
{ 
 public: 
    McdBurger (){}; 
    ~McdBurger (){};

 void MakeBurger() 
{ 
    cout << "make McD Burget" <<endl; 
} 
};

class CoreFactory
{
    virtual Pizza* MakePizza() = 0;
    virtual Burger* MakeBurger() = 0;
}

class FactoryA : public CoreFactory
{
 public:
      Pizza* MakePizza() {return new CheesePizza;}
      Burger* MakeBurger() {return new KfcBurger;}
}

class FactoryB : public CoreFactory
{
 public:
      Pizza* MakePizza() {return new GreekPizza;}
      Burger* MakeBurger() {return new McdBurger;}
}

 

posted on 2013-11-09 17:29  Halibaba  阅读(262)  评论(0编辑  收藏  举报