前言 模式介紹 在之前簡單工廠模式中,我們介紹了簡單工廠模式的缺陷是違背了開放 封閉原則。如果在面館中添加了烤海參,那將會修改waiter工廠類。違背了類內封閉原則。 還以面館為例,現在兩種面,用一個服務員來賣就可以,如果這個服務員不幹了,後面賣面的廚師需要兼職頂替服務員,但是廚師又不能離開竈台,就 ...
前言
模式介紹
在之前簡單工廠模式中,我們介紹了簡單工廠模式的缺陷是違背了開放-封閉原則。如果在面館中添加了烤海參,那將會修改waiter工廠類。違背了類內封閉原則。
還以面館為例,現在兩種面,用一個服務員來賣就可以,如果這個服務員不幹了,後面賣面的廚師需要兼職頂替服務員,但是廚師又不能離開竈台,就將模式改成了視窗排隊式,一隊海參炒麵,另一隊辣根湯麵。每個視窗分別有一個廚師放飯,一個會做海參炒麵,另一個會做辣根湯麵。老闆覺得這種模式挺好,萬一來了一個會做烤海參的,就只需要開一個烤海參的視窗就好了,不需要重新要服務員學習,因為烤海參的就會賣。這就變成了工廠模式。
UML類圖
這裡涉及到2種類①我,客戶端,排隊買飯。②做飯廚師類,工廠類,為我生成飯。③菜品類,生成菜品類。具體關係如下UML類圖:
代碼實例
下麵是noodle類,是為工廠類使用的,繼承他就可以擴展noodle類別:
#ifndef NOODLE_H
#define NOODLE_H
class noodle
{
public:
noodle() {}
~noodle() {}
virtual void eating() = 0;
};
#endif // NOODLE_H
下麵是海參炒麵類,繼承了noodle,實現eating方法,吃海參炒麵:
#ifndef HAISHENNOODLE_H
#define HAISHENNOODLE_H
#include "noodle.h"
class haishennoodle : public noodle
{
public:
haishennoodle();
~haishennoodle();
virtual void eating();
};
#endif // HAISHENNOODLE_H
#include <iostream>
#include "haishennoodle.h"
haishennoodle::haishennoodle()
{
}
haishennoodle::~haishennoodle()
{
}
void haishennoodle::eating()
{
std::cout << "我是海參炒麵,裡面沒有海參哦!!吃的時候註意!" << std::endl;
}
下麵是辣根湯麵,繼承了noodle,實現eating方法,吃辣根湯麵:
#ifndef LAGENNOODLE_H
#define LAGENNOODLE_H
#include "noodle.h"
class lagennoodle : public noodle
{
public:
lagennoodle();
~lagennoodle();
virtual void eating();
};
#endif // LAGENNOODLE_H
#include <iostream>
#include "lagennoodle.h"
lagennoodle::lagennoodle()
{
}
lagennoodle::~lagennoodle()
{
}
void lagennoodle::eating()
{
std::cout << "我是辣根湯麵,吃完嗆的哼啊!!!" << std::endl;
}
下麵是waiter工廠的基類。所有工廠都繼承這個類:
#ifndef WAITER_H
#define WAITER_H
class noodle;
class waiter
{
public:
waiter() {}
~waiter() {}
virtual noodle *createnoodle() = 0;
};
#endif // WAITER_H
下麵是海參廚師(工廠1),海參廚師只管做海參炒麵,重寫了createnoodle方法:
#ifndef HAISHEN_H
#define HAISHEN_H
#include "waiter.h"
class noodle;
class haishen : public waiter
{
public:
haishen();
~haishen();
virtual noodle *createnoodle();
};
#endif // HAISHEN_H
#include <iostream>
#include "haishen.h"
#include "haishennoodle.h"
haishen::haishen()
{
}
haishen::~haishen()
{
}
noodle *haishen::createnoodle()
{
std::cout << "面是我炒得,我的名字叫海參!!!" << std::endl;
return new haishennoodle();
}
下麵是辣根廚師(工廠1),辣根廚師只管做辣根湯麵,重寫了createnoodle方法:
#ifndef LAGEN_H
#define LAGEN_H
#include "waiter.h"
class lagen : public waiter
{
public:
lagen();
~lagen();
virtual noodle *createnoodle();
};
#endif // LAGEN_H
#include <iostream>
#include "lagen.h"
#include "lagennoodle.h"
lagen::lagen()
{
}
lagen::~lagen()
{
}
noodle *lagen::createnoodle()
{
std::cout << "吃辣根湯麵,你不覺得嗆得哼嗎??" << std::endl;
return new lagennoodle();
}
下麵是客戶端,客戶端通過類別,使用相應的工廠類建立相應的實例:
#include <iostream>
#include <string.h>
#include "haishen.h"
#include "lagen.h"
#include "noodle.h"
using namespace std;
char *product_list[] = {
"haishen-noodle",
"lagen-noodle",
NULL
};
int main()
{
char *p = NULL;
char *pd = "haishen-noodle";
int i = 0;
waiter *w = NULL;
noodle *n = NULL;
for(p = product_list[i]; p != NULL; i++, p = product_list[i]) {
if(strncmp(pd, p, strlen(pd)) == 0) {
if(i == 0) {
w = new haishen();
} else if(i == 1) {
w = new lagen();
} else {
cout << "對不起,請您排在隊內!!!" << std::endl;
break;
}
}
}
if(w) n = w->createnoodle();
if(n) n->eating();
if(w) {
delete w; w = NULL;
}
if(n) {
delete n; n = NULL;
}
return 0;
}
下麵是CMakeList.txt文件,幫助生成Makefile:
cmake_minimum_required(VERSION 2.8)
project(noodle-factory)
set(SRC_LIST main.cpp noodle.h waiter.h haishen.h haishen.cpp haishennoodle.h haishennoodle.cpp
lagennoodle.h lagennoodle.cpp lagen.h lagen.cpp)
add_executable(${PROJECT_NAME} ${SRC_LIST})
編譯運行結果
代碼下載鏈接是:https://github.com/erguangqiang/freesir_headfirst/blob/master/noodle-factory.tar.gz
使用cmake生成Makefile,並編譯出可執行程式noodle。運行結果如下:
erguangqiang@elab$./noodle-factory
面是我炒得,我的名字叫海參!!!
我是海參炒麵,裡面沒有海參哦!!吃的時候註意!
結束
工廠模式解決了簡單工廠違背了的開放-封閉原則。雖然累的結構變的複雜了,但是對於擴展性得到了很大的提高。