天天看点

编程模式 之美 -- 抽象工厂模式

文章目录

  • ​​1. 解决问题​​
  • ​​2. 应用场景​​
  • ​​3. 实现如下:​​
  • ​​C++实现​​
  • ​​C语言实现​​
  • ​​4. 缺点​​

1. 解决问题

在工厂方法模式中,我们卖衣服。此时我们为每一种衣服创建不同的工厂,帽子有一个工厂专门创建,裤子有一个工厂专门创建,T恤有一个工厂专门创建。这样的方式保证了代码设计的开闭原则(对扩展开发,对修改关闭),解决了简单工厂模式中暴露的问题。

但是又凸显了新的问题,假如现在优衣库这个大工厂 里面需要生产不同的种类的衣服,我们需要创建一堆工厂。同时香蕉共和国 这个另一个大工厂也需要生产不同种类的衣服,我们又需要创建一堆工厂。在这种情况下,代码会增加很多重复逻辑。

于是抽象工厂模式推出,将帽子封装为一个工厂, 支持生产优衣库的帽子和香蕉共和国的帽子。将裤子封装为另一个工厂,用来生产优衣库的裤子和香蕉共和国的裤子。

2. 应用场景

  • 对象之间存在关联,两个对象使用同一个工厂生产,降低程序复杂度,减少不必要的重复逻辑。
  • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构
  • 对象数量比较庞大,维护多个工厂则程序的复杂度过高,由工厂方法模式变更为抽象工厂模式

3. 实现如下:

C++实现

实现功能:仍然是生产衣服,我们使用抽象工厂模式 将优衣库的帽子和香蕉共和国的帽子统一生产,将优衣库的裤子和香蕉共和国的裤子统一生产。

#include <iostream>

using namespace std;

class Hat{
    public:
    virtual void createHat(void) = 0;
    virtual ~Hat(){}
};

/*优衣库的帽子*/
class kuHat: public Hat {
    public:
    kuHat(){
        cout << "kuHat::kuHat()" << endl;
    }
    
    virtual void createHat(void) {
        cout << "kuHat::createHat()" << endl;
    }
    
    ~kuHat(){
        cout << "kuHat::delete()" << endl;
    }    
};

/*香蕉共和国的帽子*/
class bananHat: public Hat{
    public:
    bananHat(){
        cout << "bananHat::bananHat()" << endl;
    }
    
    virtual void createHat(void) {
        cout << "bananHat::createHat()" << endl;
    }
    
    ~bananHat(){
        cout << "bananHat::delete()" << endl;
    }      
};

class Paths{
    public:
    virtual void createPaths(void) = 0;
    virtual ~Paths(){}    
};

/*优衣库的裤子*/
class kuPaths: public Paths{
    public:
    kuPaths(){
        cout << "kuPaths::kuPaths()" << endl;
    }
    
    virtual void createPaths(void) {
        cout << "kuPaths::createPaths()" << endl;
    }
    
    ~kuPaths(){
        cout << "kuPaths::delete()" << endl;
    }      
};

/*香蕉共和国的裤子*/
class bananPaths: public Paths{
    public:
    bananPaths(){
        cout << "bananPaths::bananPaths()" << endl;
    }
    
    virtual void createPaths(void) {
        cout << "bananPaths::createPaths()" << endl;
    }
    
    ~bananPaths(){
        cout << "bananPaths::delete()" << endl;
    }      
};

/*抽象工厂类*/
class Factory {
    public:
    virtual Hat *createHat() = 0;
    virtual Paths *createPaths() = 0;
};

/*优衣库的工厂,用来创建优衣库的衣服*/
class FactoryKu: public Factory{
    public:
    Hat *createHat(){
        return new kuHat();
    }
    
    Paths *createPaths(){
        return new kuPaths();
    }
};

/*香蕉共和国的工厂,用来创建香蕉共和国的衣服*/
class FactoryBanan: public Factory {
    public:
    Hat *createHat(){
        return new bananHat();
    }
    
    Paths *createPaths() {
        return new bananPaths();
    }
};

int main() {
    /*创建一个优衣库的工厂,进行优衣库的衣服的生产,包括裤子和帽子*/
    Factory *factory1 = new FactoryKu();
    Hat *kuhat = factory1 -> createHat();
    Paths *kupaths = factory1 -> createPaths();
    
    kuhat -> createHat();
    kupaths -> createPaths();
    
    if(factory1) {
        delete factory1;
        factory1 = NULL;
    }
    
    if(kuhat) {
        delete kuhat;
        kuhat = NULL;
    }
    
    if(kupaths) {
        delete kupaths;
        kupaths = NULL;
    }
    return 0;
}      

编译运行如下

kuHat::kuHat()
kuPaths::kuPaths()
kuHat::createHat()
kuPaths::createPaths()
kuHat::delete()
kuPaths::delete()      
C语言实现

实现功能:工厂商店分别 售卖白苹果、红苹果、白葡萄、红葡萄

/*C语言实现抽象工厂模式*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

enum {WHITE,RED};

/*苹果基类*/
typedef struct _Apple {
  void (*print_apple)(void);
}Apple;

/*葡萄基类*/
typedef struct _Grape {
  void (*print_grape)(void);
}Grape;

void print_white_apple(void) 
{
  printf("I'am a white apple!\n");
  return;
}

void print_red_apple(void)
{
  printf("I'am a red apple!\n");
  return;
}
void print_white_grape(void)
{
  printf("I'am a white grape!\n");
  return;
}
void print_red_grape(void)
{
  printf("I'am a red grape!\n");
  return;
}

/*水果商店*/
typedef struct _FruitShop {
  Apple * (*sell_apple)(void);
  Grape * (*sell_grape)(void);
}FruitShop;

Apple* sell_white_apple(void)
{
  Apple* tmp_apple = (Apple*)malloc(sizeof(Apple));
  assert(NULL != tmp_apple);

  tmp_apple->print_apple = print_white_apple;

  return tmp_apple;
}

Apple* sell_red_apple(void)
{
  Apple* tmp_apple = (Apple*)malloc(sizeof(Apple));
  assert(NULL != tmp_apple);

  tmp_apple->print_apple = print_red_apple;

  return tmp_apple;
}

Grape* sell_white_grape(void)
{
  Grape* tmp_grape = (Grape*)malloc(sizeof(Grape));
  assert(tmp_grape != NULL);

  tmp_grape->print_grape = print_white_grape;
  return tmp_grape;
}
Grape* sell_red_grape(void)
{
  Grape* tmp_grape = (Grape*)malloc(sizeof(Grape));
  assert(tmp_grape);

  tmp_grape->print_grape = print_red_grape;

  return tmp_grape;
}

/*工厂商店,卖不同颜色的苹果和葡萄*/
FruitShop* create_fruit_shop(int color)
{
  FruitShop* fruitshop = (FruitShop*)malloc(sizeof(FruitShop));
  assert(fruitshop != NULL);

  if (color == WHITE) {
    fruitshop->sell_apple = sell_white_apple;
    fruitshop->sell_grape = sell_white_grape;
  }
  else if (color == RED) {
    fruitshop->sell_apple = sell_red_apple;
    fruitshop->sell_grape = sell_red_grape;
  }

  return fruitshop;
}

int main()
{
  FruitShop* fruitshop = create_fruit_shop(RED);

  Apple *ap = fruitshop->sell_apple();
  Grape *gp = fruitshop->sell_grape();

  ap->print_apple();
  gp->print_grape();

  if (ap != NULL) {
    free(ap);
  }
  if (gp != NULL) {
    free(gp);
  }
  if (fruitshop != NULL) {
    free(fruitshop);
  }

  return 0;
}      
I'am a red apple!
I'am a red grape!      

4. 缺点

  1. 当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。(按照如上C++代码,我们买衣服,当我们增加一种衣服:裙子的时候,只需要增加一个新的生产裙子的工厂就可以,不需要修改原的衣服种类的代码)
  2. 当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。(当我们又增加了名创优品的种类时,我们之前所有的类包括:hat,Paths,还有对应的工厂类都需要修改 )