设计模式(4):生成器模式(Builder)
1. 說(shuō)明
什么是生成器模式
生成器模式是創(chuàng)建型模式的一種,指使用多個(gè)實(shí)例通過(guò)一定的步驟來(lái)生成所需的類(lèi)的實(shí)例,這里的步驟是相同的,但是通過(guò)傳遞不同的參數(shù)來(lái)達(dá)到生成不同實(shí)例的目的。
意圖
將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。
使用的場(chǎng)合
在以下情況使用Builder模式:
- 當(dāng)創(chuàng)建復(fù)雜對(duì)象的算法應(yīng)該獨(dú)立于該對(duì)象的組成部分以及它們的裝配方式時(shí);
- 當(dāng)構(gòu)造過(guò)程必須允許被構(gòu)造的對(duì)象有不同的表示時(shí)。
效果
優(yōu)點(diǎn)
缺點(diǎn)
2. 示例
2.1 框架
我們假設(shè)一個(gè)快餐店的商業(yè)案例,其中,一個(gè)典型的套餐可以是一個(gè)漢堡(Burger)和一杯冷飲(Cold drink)。漢堡(Burger)可以是素食漢堡(Veg Burger)或雞肉漢堡(Chicken Burger),它們是包在紙盒中。冷飲(Cold drink)可以是可口可樂(lè)(coke)或百事可樂(lè)(pepsi),它們是裝在瓶子中。
我們將創(chuàng)建一個(gè)表示食物條目(比如漢堡和冷飲)的 Item 接口和實(shí)現(xiàn) Item 接口的實(shí)體類(lèi),以及一個(gè)表示食物包裝的 Packing 接口和實(shí)現(xiàn) Packing 接口的實(shí)體類(lèi),漢堡是包在紙盒中,冷飲是裝在瓶子中。
然后我們創(chuàng)建一個(gè) Meal 類(lèi),通過(guò)結(jié)Item 來(lái)創(chuàng)建不同類(lèi)型的 Meal 對(duì)象的 MealBuilder。Demo 使用 MealBuilder 來(lái)創(chuàng)建一個(gè) Meal。
結(jié)構(gòu)圖如下:
2.2 代碼實(shí)現(xiàn)
2.2.1 抽象接口類(lèi)
Packing.h
#ifndef __PACKING__ #define __PACKING__ class Packing {public:virtual string pack() = 0; }; #endifPacking 是食品包裝的抽象接口;
Item.h
#ifndef __ITEM__ #define __ITEM__class Packing {public:virtual string pack() = 0; }class Item{public:virtual string name() = 0;virtual Packing *packing() = 0;virtual float price() = 0; }; #endifItem 則是食物條目的抽象接口類(lèi);
2.2.2 實(shí)現(xiàn)Packing接口的實(shí)體類(lèi)
Wrapper.h
#ifndef __WRAPPER__ #define __WRAPPER__#include "Packing.h"class Wrapper : public Packing{public:string pack() {return "Wrapper";}; }; #endifBottle.h
#ifndef __BOTTLE__ #define __BOTTLE__#include "Packing.h"class Bottle : public Packing{public:string pack() {return "Bottle";}; }; #endif2.2.3 創(chuàng)建實(shí)現(xiàn) Item 接口的抽象類(lèi),該類(lèi)提供了默認(rèn)的功能
Burger.h
#ifndef __BURGER__ #define __BURGER__#include "Item.h" #include "Packing.h" #include "Wrapper.h" #include "Bottle.h"class Burger : public Item{public:Packing *packing() {return new Wrapper();}; };class VegBurger : public Burger{public:float price() {return 25.0;};string name() {return "Veg Burger";}; };class ChickenBurger : public Burger{public:float price() {return 50.0;};string name() {return "ChickenBurger";}; }; #endifDrink.h
#ifndef __DRINK__ #define __DRINK__#include "Item.h" #include "Packing.h" #include "Wrapper.h" #include "Bottle.h"class Drink : public Item{public:Packing *packing() {return new Bottle();}; };class Coke : public Drink{public:float price() {return 30.0;};string name() {return "Coke";}; };class Pepsi : public Drink{public:float price() {return 35.0;};string name() {return "Pepsi";}; }; #endif2.2.4 創(chuàng)建一個(gè) Meal 類(lèi),帶有上面定義的 Item 對(duì)象
Meal.h
#ifndef __MEAL__ #define __MEAL__#include <vector>#include "Item.h"using namespace std;class Meal{public:Meal() {items = new vector<Item*>;};void AddItem(Item *it) {items->push_back(it);};float GetCost();void ShowItem();private:vector<Item*> *items; }; #endifMeal.cpp
#include <iostream>#include "Meal.h" #include "Burger.h" #include "Drink.h"float Meal::GetCost() {float cost = 0;auto item = items->begin();while(item != items->end()){cost += (*item)->price();item++;}return cost; }void Meal::ShowItem() {auto item = items->begin();while(item != items->end()){std::cout << "Item: " << (*item)->name() << ", Packing: " << (*item)->packing()->pack() << ", Price: " << (*item)->price() << std::endl;item++;} }2.2.5 創(chuàng)建一個(gè) MealBuilder 類(lèi),實(shí)際的 builder 類(lèi)負(fù)責(zé)創(chuàng)建 Meal 對(duì)象
MealBuilder.h
#ifndef __MEALBUILDER__ #define __MEALBUILDER__#include "Meal.h"class MealBuilder{public:Meal *PrepareVegMeal();Meal *PrepareNonVegMeal(); }; #endifMealBuilder.cpp
#include "MealBuilder.h" #include "Burger.h" #include "Drink.h"Meal *MealBuilder::PrepareVegMeal() {Item *vb = (Item *)new VegBurger();Item *coke = (Item *)new Coke();Meal *meal = new Meal();meal->AddItem(vb);meal->AddItem(coke);return meal; }Meal *MealBuilder::PrepareNonVegMeal() {Item *cb = (Item *)new ChickenBurger();Item *pp = (Item *)new Pepsi();Meal *meal = new Meal();meal->AddItem(cb);meal->AddItem(pp);return meal; }2.2.6 Demo 使用 MealBuider 來(lái)演示建造者模式(Builder Pattern)
Demo.cpp
#include "MealBuilder.h"int main(int argc, char **argv) {MealBuilder *mb = new MealBuilder();Meal *vegm = mb->PrepareVegMeal();vegm->ShowItem();std::cout << "VegMeal price: " << vegm->GetCost() << std::endl;Meal *nvegm = mb->PrepareNonVegMeal();nvegm->ShowItem();std::cout << "VegMeal price: " << nvegm->GetCost() << std::endl;return 0; }2.3 編譯運(yùn)行
g++ *.cpp ./a.out2.4 結(jié)果
Item: Veg Burger, Packing: Wrapper, Price: 25 Item: Coke, Packing: Bottle, Price: 30 VegMeal price: 55 Item: ChickenBurger, Packing: Wrapper, Price: 50 Item: Pepsi, Packing: Bottle, Price: 35 VegMeal price: 853. 總結(jié)
Builder模式與Abstract Factory或Factory模式相似,都可以創(chuàng)建復(fù)雜對(duì)象,但是不同之處在于Builder模式著重于一步步構(gòu)造一個(gè)復(fù)雜對(duì)象,在最后一步返回產(chǎn)品,強(qiáng)調(diào)構(gòu)造細(xì)節(jié),而后兩者著重于多個(gè)系列的產(chǎn)品一次生成,通常產(chǎn)品是立即返回的。
參考資料
《設(shè)計(jì)模式 可復(fù)用面向?qū)ο筌浖幕A(chǔ)》
https://www.runoob.com/design-pattern/builder-pattern.html
總結(jié)
以上是生活随笔為你收集整理的设计模式(4):生成器模式(Builder)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Centos禁止屏幕虚拟键盘弹出
- 下一篇: IE恶意修改防护大法(转)