建造者模式

来源:互联网 发布:济南软件外包服务 编辑:程序博客网 时间:2024/06/06 13:57

一、 建造者模式概述

建造者模式用于创建一个包含多个组成部分的复杂对象,它可以返回一个完整的产品对象给用户。用户无须知道创建过程和内部组成细节,就可以直接创建一个完整的对象。现实世界中有很多复杂的对象,它们拥有很多组成部分,如电脑,它由主机、显示器、鼠标、键盘等组成。

在软件开发过程中,也有很多和电脑一样复杂的对象,它们拥有一系列成员属性。在这些复杂对象中,可能存在一些限制条件,如某些属性没有被赋值则复杂对象就不能作为一个完整的产品使用。如一台电脑没有主机,则它就没有办法使用。有些属性的赋值必须按照一定的顺序,否则赋值操作无法完成等。组合这些部件(属性)的过程往往是复杂的,所以这些部件(属性)的组合往往被抽取到一个被称为建造者的对象中进行。建造者模式的目的就是让建造者返回一个完整的产品对象给客户端,而客户端不需要关心该对象包含的属性和建造过程。

建造者模式将一个复杂对象的构建与它的表示分离,使用得同样的构建过程可以创建不同的表示形式。用户只需指定复杂对象的类型和内容就可以让建造者构建它们,而不需要知道它们构建细节。下图是一个典型的建造者模式结构图


从图上我们可以看出,建造者模式通常包含以下角色

Builder(抽象建造者):它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两种方法,一类是buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是getResult(),它们用于返回复杂对象。

ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的构造和装配方法,并提供一个方法返回创建好的复杂产品对象。

Product(产品角色):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。

Director(指挥者):它负责安排复杂对象的建造次序,它可以在其construct() 方法中调用建造者对象的部件构造与装配方法来完成复杂对象的建造。用户只需与指挥者交互,在客户端确定具体建造者的类型,然后通过指挥者类的构造函数或者set方法将该对象传入指挥者类中。

 

二、建造者模式实例1

下面对上图稍加改造,设计出下面这个类图


该实例的实现源码如下

#include <string>#include <iostream>#include <vector>using namespace std;class Product {private:vector<string> product;public:void add(string str){product.push_back(str);}void show(){vector<string>::iterator p = product.begin();while (p != product.end()){cout << *p << endl;p++;}}};class Builder{public:virtual void builderA() = 0;virtual void builderB() = 0;virtual Product* getResult() = 0;};class ConcreteBuilder1 : public Builder{private:Product* product;public:ConcreteBuilder1(){product = new Product();}virtual void builderA(){product->add("Product_by_ConcreteBuilder1_1");}virtual void builderB(){product->add("Product_by_ConcreteBuilder1_2");}virtual Product* getResult(){return product;}};class ConcreteBuilder2 : public Builder{private:Product* product;public:ConcreteBuilder2(){product = new Product();}virtual void builderA(){product->add("Product_by_ConcreteBuilder2_1");}virtual void builderB(){product->add("Product_by_ConcreteBuilder2_2");}virtual Product* getResult(){return product;}};class Directotr{public:void construct(Builder* temp){temp->builderA();temp->builderB();}};int main(){Directotr* direct = new Directotr();Builder* builder1 = new ConcreteBuilder1();Builder* buidler2 = new ConcreteBuilder2();direct->construct(builder1);Product* droduct1 = builder1->getResult();droduct1->show();direct->construct(buidler2);Product* product2 = buidler2->getResult();product2->show();return 0;}

  注意在这个程序里面的ConcreteBuilder1和ConcreteBuilder2的builderA()和builderB()函数中,都只是往vector里加字符串,这里我是把字符串当成抽象组件。在实际开发中,可以根据实际需要,往vector里添加实际的组件以构成产品,而不必局限于添加字符串。

 

三、建造者模式实例2

下面再通过一个模拟的订餐系统模式来加深对建造者模式的理解,在这个订餐系统中,定义了两种类型的套餐,它们的组成部分是不同的,每种套餐中各有一份主食和饮料。虚拟的服务员Waiter会根据客户的要求来装配这些组成部分,构造一个完整的套餐,并返回给客户。该实例的类图如下


实例的代码如下

(1)产品类Meal(套餐类):

public class Meal {private String food;private String drink;public void setFood(String food){this.food = food;}public void setDrink(String drink){this.drink = drink;}public String getFood(){return (this.food);}public String getDrink(){return (this.drink);}}


(2)抽象建造者类MealBuilder(套餐建造者类)

public abstract class MealBuilder {protected Meal meal;public abstract void buildFood();public abstract void buildDrink();public MealBuilder(){meal = new Meal();}public Meal getMeal(){return meal;}}


(3)具体建造者类SubMealBuilderA(A套餐建造者类)

public class SubMealBuilderA extends MealBuilder{@Overridepublic void buildFood() {meal.setFood("A hamburger");}@Overridepublic void buildDrink() {meal.setDrink("A cup of coke");}}

(4)具体建造者类SubMealBuilderB(B套餐建造者类)

public class SubMealBuilderB extends MealBuilder{@Overridepublic void buildFood() {meal.setFood("A sandwich");}@Overridepublic void buildDrink() {meal.setDrink("A cup of coffee");}}

(5)指挥者类Waiter(在此服务员类充当指挥者)

public class Waiter {private MealBuilder mb;public void setMealBuilder(MealBuilder mb){this.mb = mb;}public Meal construct(){mb.buildFood();mb.buildDrink();return mb.getMeal();}}

(6)客户端(测试类)

public class Client {public static void main(String args[]){//Determine the combo meal typeMealBuilder mb = new SubMealBuilderA();//The waiter is a commanderWaiter waiter = new Waiter();//The waiter prepare the mealwaiter.setMealBuilder(mb);//Customer get the mealMeal meal = waiter.construct();System.out.println("The composition of the combo meal:");System.out.println(meal.getFood());System.out.println(meal.getDrink());}}

  如果需要增加新的具体建造者,只需增加一个新的具体建造者类继承抽象建造者类,再实现其中声明的抽象部件组装方法,就可以使用新的具体建造者构造新的类型的套餐。上面的mb对象可以通过配置文件来设置,让程序在运行时根据读取配置文件的信息,来设置具体的创建者,这里为省事,直接写死了。

 

三、小结

在建造者模式中,用户不用知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象;每一个具体建造者都是相互独立的因此可以方便的替换或增加新的具体建造者,用户使用不同的具体建造者,就可以得到不同的产品对象。

建造者模式所创建的产品一般具有较多的工同点,其组成部分相似,如果产品差异大,那么该模式就不可用了;如果产品内部的变化复杂,会导致需要定义很多具体建造者类来实现这种变化,导致系统就得很大很复杂。




0 0
原创粉丝点击