建造者模式—Builder
1.模式定义:
建造者模式(Builder ):将一个复杂对象的构建与它的表示分离(解耦),使得同样的构建过程可以创建不同的表示(产品)。
2.模式结构
- builder:抽象建造者
- concretebuilderABC,concretebuilderAC :具体建造者
- director:指挥者
- product:产品角色
3.代码分析
- 3.1 main.cpp
#include<iostream>
#include"product.hpp"
#include"concretebuilder.hpp"
#include"director.hpp"
using namespace std;
int main() {
cout << "==============concretebuilderABC=======================" << endl;
product* pro_abc = new product();
concretebuilderABC* builder_abc = new concretebuilderABC(pro_abc);
director drc_abc;
drc_abc.set_builder(builder_abc);
pro_abc = drc_abc.construct();
pro_abc->show();
cout << "==============concretebuilderAC=======================" << endl;
product* pro_ac = new product();
concretebuilderAC* builder_ac = new concretebuilderAC(pro_ac);
director drc_ac;
drc_ac.set_builder(builder_ac);
pro_ac = drc_ac.construct();
pro_ac->show();
return 0;
}
- 3.2 抽象建造者: builder.hpp
#ifndef BUILDER_HPP
#define BUILDER_HPP
// 抽象建造接口
class builder
{
public:
virtual ~builder(){};
virtual void build_partA(){};
virtual void build_partB(){};
virtual void build_partC(){};
virtual product* get_product(){ return nullptr; };
};
#endif // BUILDER_HPP
- 3.3 具体建造者: concretebuilder.hpp
#ifndef CONCRETE_BUILDER_HPP
#define CONCRETE_BUILDER_HPP
#include<iostream>
#include"product.hpp"
#include"builder.hpp"
using namespace std;
// 具体建造类
class concretebuilderABC: public builder
{
private:
product* m_product;
public:
concretebuilderABC(product* pro): m_product(pro){};
~concretebuilderABC(){
delete m_product;
};
void build_partA(){
cout << "concretebuilderABC::build_partA" << endl;
m_product->set_A();
};
void build_partB(){
cout << "concretebuilderABC::build_partB" << endl;
m_product->set_B();
};
void build_partC(){
cout << "concretebuilderABC::build_partC" << endl;
m_product->set_C();
};
product* get_product() {
return m_product;
};
};
// 具体建造类
class concretebuilderAC: public builder
{
private:
product* m_product;
public:
concretebuilderAC(product* pro): m_product(pro){};
~concretebuilderAC(){
delete m_product;
};
void build_partA(){
cout << "concretebuilderAC::build_partA" << endl;
m_product->set_A();
};
void build_partB(){
};
void build_partC(){
cout << "concretebuilderAC::build_partC" << endl;
m_product->set_C();
};
product* get_product() {
return m_product;
};
};
#endif // CONCRETE_BUILDER_HPP
- 3.4 指挥者: director.hpp
#ifndef DIRECTOR_HPP
#define DIRECTOR_HPP
#include"product.hpp"
#include"builder.hpp"
// 指挥者
class director
{
private:
builder* m_builder;
public:
director(){};
~director(){
delete m_builder;
};
void init_builder(builder* bld){
if (!bld) {
return;
}
m_builder = bld;
};
void set_builder(builder* bld){
init_builder(bld);
};
product* construct() {
if (!m_builder) {
return nullptr;
}
m_builder->build_partA();
m_builder->build_partB();
m_builder->build_partC();
return m_builder->get_product();
};
};
#endif // DIRECTOR_HPP
- 3.5 产品: product.hpp
#ifndef PRODUCT_HPP
#define PRODUCT_HPP
#include<iostream>
using namespace std;
// 产品
class product{
public:
product(){};
~product(){};
void set_A() {
cout << "product::set_A" << endl;
};
void set_B() {
cout << "product::set_B" << endl;
};
void set_C() {
cout << "product::set_C" << endl;
};
void show(){
cout << "product::show" << endl;
};
};
#endif // PRODUCT_HPP
- 3.6 实验结果:
==============concretebuilderABC=======================
concretebuilderABC::build_partA
product::set_A
concretebuilderABC::build_partB
product::set_B
concretebuilderABC::build_partC
product::set_C
product::show
==============concretebuilderAC=======================
concretebuilderAC::build_partA
product::set_A
concretebuilderAC::build_partC
product::set_C
product::show
4.优缺点
-
4.1 优点
- 4.1.1 在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 4.1.2 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
- 4.1.3 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
- 4.1.4 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
-
4.2 缺点
- 4.2.1 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 4.2.2 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
5.模式分析
-
5.1 抽象建造者类中定义了产品的创建方法和返回方法;
-
5.2 建造者模式的结构中还引入了一个指挥者类Director,该类的作用主要有两个:一方面它隔离了客户与生产过程;另一方面它负责控制产品的生成过程。指挥者针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象;
-
5.3 在客户端代码中,无须关心产品对象的具体组装过程,只需确定具体建造者的类型即可,建造者模式将复杂对象的构建与对象的表现分离开来,这样使得同样的构建过程可以创建出不同的表现。
6.实例:肯德基点餐(go代码实现)
- 6.0: main.go
package main
import (
"fmt"
"./builder"
)
func test_builder() {
cbld := builder.NewConcreteBuilder()
fmt.Println("before builder meal:")
cbld.GetMeal().Show()
drc := builder.NewDirector(cbld)
drc.Construct("keli", "zhaji")
fmt.Println("afore builder meal:")
cbld.GetMeal().Show()
}
func main() {
test_builder()
}
- 6.1:套餐:meal.go
package builder
import "fmt"
// 套餐
type Meal struct {
food string
drink string
}
func NewMeal(food, drink string) *Meal {
return &Meal{
food: food,
drink: drink,
}
}
func (m *Meal) set_food(food string) {
m.food = food
}
func (m *Meal) set_drink(drink string) {
m.drink = drink
}
func (m *Meal) Show() {
fmt.Println("food:", m.food)
fmt.Println("drink:", m.drink)
}
- 6.2: 创建类:builder.go
package builder
// 创建接口
type IBuilder interface {
BuildDrink(string)
BuildFood(string)
}
// =====================================================
// 具体创建
type ConcreteBuilder struct {
meal *Meal
}
func NewConcreteBuilder() *ConcreteBuilder {
return &ConcreteBuilder{
meal: NewMeal("", ""),
}
}
func (cbld *ConcreteBuilder) BuildDrink(drink string) {
cbld.meal.set_drink(drink)
}
func (cbld *ConcreteBuilder) BuildFood(food string) {
cbld.meal.set_food(food)
}
func (cbld ConcreteBuilder) GetMeal() *Meal {
return cbld.meal
}
- 6.3: 指挥者:director.go
package builder
// 指挥者
type Director struct {
Builder IBuilder
}
func NewDirector(builder IBuilder) *Director {
return &Director{
Builder: builder,
}
}
// 构造具体的套餐
func (drc *Director) Construct(drink, food string) {
drc.Builder.BuildDrink(drink)
drc.Builder.BuildFood(food)
}
func (drc *Director) SetMealBuilder(builer IBuilder) {
drc.Builder = builer
}
- 6.4 执行结果:
before builder meal:
food:
drink:
afore builder meal:
food: zhaji
drink: keli