zoukankan      html  css  js  c++  java
  • 第6章 创建型模式—建造者模式

    1. 建造者(Builder,或生成器)模式的定义

    (1)将一个复杂对象构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

      ①上述提到的“构建”是指构造过程的算法(即构造顺序,位于director类中),“表示”指生成各部件的具体细节(或叫实现,位于Builder或其子类中)。

      ②由指导者(director)来指导构造过程,而建造者(builder)负责每步的对象的具体实现组装各部件

      ③指导者可以重用构建过程,而生成器是可以被切换的具体实现

    (2)建造者模式的结构和说明

     

      ①Builder:建造者接口,定义创建一个Product对象所需要的各个部件的接口。

      ②ConcreteBuilder:具体的建造者实现,实现各个部件的创建,并负责组装Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法。

      ③Director:指导员,主要用来使用Builder接口,以一个统一年过程来构建所需要的Product对象。

      ④Product:产品,表示被建造者构建的复杂对象,包含多个部件。

    2. 建造者模式的思考

    (1)建造者模式的功能:构建复杂的产品,而且是细化的、分步骤的构建产品。也就是其重在一步一步解决构造复杂对象的问题。

      ①构建的过程是统一的、固定不变的(则指导者来制定)。变化的是的每步的具体的实现,由建造者来实现。

      ②建造者模式的重心在于分离构建算法具体构造的实现

    (2)建造者模式的构成——两个部分

      ①Builder接口:这里定义了如何构建各个部件,也就是知道每个部件的功能是如何实现的,以及如何装配这些部件到产品中去。即部件构造和产品装配

      ②Director知道按什么流程来构建产品,负责整体的构建算法,通常是分步骤来执行。这里要强调的是,整体构建算法是固定的。当Director实现整体构建算法的时候,遇到需要创建和组合具体部件的时候,就会把这些具体的实现委托给Builder去完成

    【编程实验】建造神舟飞船

    //创建型模式:建造者模式
    //神舟飞船的组装
    #include <stdio.h>
    #include <string>
    
    using namespace std;
    //*************************辅助类:各个部件************************
    //轨道舱
    class OrbitalModule
    {
    private:
        string name;
    public:
        OrbitalModule(string name)
        {
            this->name = name;
        }
        
        void setName(string name)
        {
            this->name = name;
        }
        
        string getName(){return name;}
    };
    
    //发动机
    class Engine
    {
    private:
        string name;
    public:
        Engine(string name)
        {
            this->name = name;
        }
        
        void setName(string name)
        {
            this->name = name;
        }
        
        string getName(){return name;}
    };
    
    //逃逸塔
    class EscapeTower
    {
    private:
        string name;
    public:
        EscapeTower(string name)
        {
            this->name = name;
        }
        
        void setName(string name)
        {
            this->name =name;
        }
        
        string getName(){return name;}
    };
    
    //最终产品Product
    class Airship
    {
    private:
        OrbitalModule* orbitalModule;  //轨道舱
        Engine* engine;                //发动机
        EscapeTower* escapeTower;      //逃逸塔
    public:
        OrbitalModule* getOrbitalModule(){return orbitalModule;}
        void setOrbitalModule(OrbitalModule* orbitalModule)
        {
            this->orbitalModule =orbitalModule;
        }    
        
        Engine* getEngine(){return engine;}
        void setEngine(Engine* engine)
        {
            this->engine =engine;
        } 
    
        EscapeTower* getEscapeTower(){return escapeTower;}
        void setEscapeTower(EscapeTower* escapeTower)
        {
            this->escapeTower =escapeTower;
        }
    
        void launch()
        {
            //检测发动机是否正常
            printf("%s
    ",engine->getName().c_str()); 
            //检测轨道舱是否正常
            printf("%s
    ",orbitalModule->getName().c_str());
            //检测逃逸塔是否正常
            printf("%s
    ",escapeTower->getName().c_str());
            
            //发射
            printf("launch...
    ");        
        }    
    };
    
    //*******************************************Builder:建造者*****************************
    //抽象建造者
    class AirshipBuilder
    {
    public:
        //构建发动机
        virtual void buildEngine() = 0;
        //构建轨道舱
        virtual void buildOrbitalModule() = 0;
        //构建逃逸塔
        virtual void buildEscapeTower() = 0;
    };
    
    //具体建造者
    class ConcreteAirshipBuilder : public AirshipBuilder
    {
    private:
        Airship airship;
    public:
    
        //Engine部件的构建
        void buildEngine()
        {
            Engine* engine =airship.getEngine();
            if (engine != NULL)
                delete engine;
            
            engine = new Engine("Airship's Engine!");
            
            //组装工作
            airship.setEngine(engine);       
        }
        
        //OrbitalModule部件的构建
        void buildOrbitalModule()
        {
            OrbitalModule* orbitalModule =airship.getOrbitalModule();
            if (orbitalModule != NULL)
                delete orbitalModule;
            
            orbitalModule = new OrbitalModule("Airship's OrbitalModule!");
            
            //组装工作
            airship.setOrbitalModule(orbitalModule);        
        }
        
        //EscapeTower部件的构建
        void buildEscapeTower()
        {
            EscapeTower* escapeTower =airship.getEscapeTower();
            if (escapeTower != NULL)
                delete escapeTower;
            
            escapeTower = new EscapeTower("Airship's EscapeTower!");
            
            //组装工作
            airship.setEscapeTower(escapeTower);          
        }
        
        //返回最终的整个产品(神舟飞船)
        Airship& getResult(){return airship;}
        
        ~ConcreteAirshipBuilder()
        {
            OrbitalModule* orbitalModule = airship.getOrbitalModule();
            if (orbitalModule != NULL)
                delete orbitalModule;
            
            Engine* engine =airship.getEngine();
            if (engine != NULL)
                delete engine;
            
            EscapeTower* escapeTower = airship.getEscapeTower();
            if (escapeTower != NULL)
                delete escapeTower;        
        }
    };
    
    //********************************Director:指导者******************************
    class Director
    {
    private:
        AirshipBuilder* builder;
    public:
        Director(AirshipBuilder* builder)
        {
            this->builder = builder;
        }
        
        //构建过程
        //1、建造者所构建的各部分是可以是先后顺序的,但本例这个顺序不明显或无关紧要。
        //2、本类中只有构建的过程(流程,也就算法),组装过程放在Builder类中。
        void construct()
        {
            //1.先构建发动机
            builder->buildEngine();
            //2.再构建轨道舱
            builder->buildOrbitalModule();
            //3.最后构建逃逸塔
            builder->buildEscapeTower();
        }
    };
    
    
    int main()
    {
        //客户端调用例子
        
        //构建者
        AirshipBuilder* builder = new ConcreteAirshipBuilder();
        
        //指导者
        Director* director = new Director(builder);
        director->construct(); //生成最终产品
        
        //测试
        Airship& airship = ((ConcreteAirshipBuilder*)builder)->getResult();
        airship.launch();
          
        delete builder;
        delete director;    
        
        return 0;
    }
    View Code

    3. 建造者模式的实现

    (1)建造者的实现

      ①Builder接口的实现中,每个buildPart方法中可以包含创建部件对象组装部件的功能。

      ②如果实现Builder时,只创建对象,没有组装功能,这里Builder实现跟抽象工厂的实现很类似。这时的Builder接口就类似于抽象工厂的接口。Builder的具体实现就类似于具体的工厂。从这点上看,Builder与抽象工厂很类似

    (2)指导者的实现

      ①指导者承担的是整体构建算法的部分,是相对不变的部分。因此在实现指导者的时候,把变化的部分分离出去是很重要的。

      ②指导员分离出去的变化部分,就到了建造者那里,指导者知道整体的构建算法,却不知道如何具体的创建和装配部件对象。

      ③在指导者的实现可以有较为复杂的算法和运算过程,在运算过程中根据需要,才会调用建造者的方法来生成部件对象。

    (3)指导者和建造者的交互

      ①指导者和建造者一般是通过Builder的buildPart方法来进行交互的。

      ②实际开发中,指导者可以按整体构建算法的步骤进行运算。到了某一步骤,需要具体创建某个部件对象了,再调用Builder中创建相应部件的方法来创建具体部件。同时把前面运算的数据传递给Builder,因为Builder内部实现创建和组装部件的时候,可能会用到这些数据。

      ③Builder创建完具体的部件对象后,会把创建好的部件对象返回指导者。指导者继续后续的算法运算,如此反复下去,直到最终产品对象创建完毕。

    (4)返回装配好的产品的方法

      ①标准的生成器模式中,在Builder实现里面会提供一个返回装配好的产品的方法,在Builder接口上是没有的。它考虑的是最终的对象一定要通过部件构建和装配,才算真正创建了。

      ②虽然指导者也参与其中,但它不负再具体部件的创建和组装,因此客户端是从Builder的实现里面获取最终装配好的产品。但也可以把这个方法加到Builder接口中。

    4. 建造者模式的优点

    (1)松散耦合

      用同一个构建算法构建出表现上完全不同的产品,实现产品构建和产品表现上的分离。Builder模式中构建算法可以复用,而具体产品表现可以灵活、方便地扩展和切换。

    (2)很容易改变产品的内部表示

      建造者只提供接口给Director使用,具体的部件创建和装配方式被Builder接口隐藏了,Director并不知道实现的细节。这样要改变产品的内部表示,只需要切换Builder的具体实现即可。不用管Director。

    (3)更好的复用:Director中构建产品过程的算法相对固定,可以复用。

    5. Builder模式的使用场合

    (1)相同的方法,不同的执行顺序,产生不同的事件结构时,可以采用建造者模式。

    (2)多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。

    (3)产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个可以使用该模式。

    6. 其他

    (1)Builder与FactoryMethod模式结合

      在Builder的实现中,通常需要选择具体的部件实现,这时可以用工厂方法来实现,通过工厂方法来获取具体的部件对象,然后再进行部件的装配。

    (2)Builder与抽象工厂模式的区别

      ①Builder模式着重于一步步构造一个复杂对象,而Abstract Factory着重于多个系列的产品对象(简单的或复杂的)

      ②Builder是最后一步返回产品,而Abstract Factory是立即返回产品

      ③抽象工厂侧重点是创建,创建零件是它的主要职责,他关心的是创建产品的结果,而builder侧重的是创建产品的过程,即顺序安排。

    (3)Builder与模板方法的区别

      ①两者都是定义了方法执行的流程。但一个前者是在Director定义的,后者是在父类定义的。

      ②在实现方法的结构上,建造者模式中使用的是组合的方式,而模板方法模式采用的是继承的方式

      ③模板方法模式是通过把不变行为搬移到父类(超类),去除了类中的重复代码来体现它的优势。而建造者是将不变部分移到Director中去,变化的部分由Builder接口去实现。

    【编程实验】将数据导出为txt和xml格式的文件

      ①文件头:包括部门ID、导出数据的日期

      ②文件体:表名称、分条描述数据

      ③文件尾:输出人的信息

    //创建型模式:建造者模式
    //将数据导出为不同格式的文件
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <list>
    
    using namespace std;
    //*************************辅助类:各个部件************************
    //文件头对象
    class Header
    {
    private:
        string depId; //部门编号
        string date;  //导出数据的日期
        
    public:
        
        void setDepId(string depId)
        {
           this->depId = depId;
        }
        
        string& getDepId(){return depId;}
        
         void setDate(string date)
        {
            this->date = date;
        }
        
        string& getDate(){return date;}   
    };
    
    //文件体
    class Body
    {
    private:
        string productId; //产品编号
        double price;     //销售价格
        double amount;    //销售数量
    public:  
        void setProductId(string productId)
        {
            this->productId = productId;
        }
        
        string& getProductId(){return productId;}
    
        void setPrice(double price)
        {
            this->price = price;
        }
        
        double getPrice(){return price;}  
    
        void setAmount(double amount)
        {
            this->amount = amount;
        }
        
        double getAmount(){return amount;}      
    };
    
    //文件尾
    class Footer
    {
    private:
        string user; //输出人
    public:   
        void setUser(string user)
        {
            this->user = user;
        }
        
        string& getUser(){return user;}      
    };
    
    //*******************************Builder*************************
    class Builder
    {
    public:
        virtual void buildHeader(Header& header) = 0; 
        virtual void buildBody(list<Body>& bodys) = 0;
        virtual void buildFooter(Footer& footer) = 0;    
    };
    
    //XmlBuilder
    class XmlBuilder : public Builder
    {
    private:
        string buffer; //用来记录文件的内容,相当于最终产品
    public:
        void buildBody(list<Body>& bodys)
        {
            buffer.append("  <Body>
    ");
            buffer.append("    <Datas TableName=Sale Details:>
    ");
            list<Body>::iterator first = bodys.begin();
            list<Body>::iterator last = bodys.end();
            
            ostringstream oss;
            while (first != last)
            {
                oss.str("");
                oss<<first->getPrice();
                
                buffer.append("      <Data>
    ");
                buffer.append("        <ProductId>"+first->getProductId()+"</ProductId>
    ");
                buffer.append("        <Price>"+oss.str()+"</Price>
    ");
                
                oss.str("");
                oss<<first->getAmount();
                
                buffer.append("        <Amount>"+oss.str()+"</Amount>
    ");            
               
                buffer.append("      </Data>
    ");
                ++first;
            } 
            buffer.append("    </Datas>
    ");
            buffer.append("  </Body>
    ");        
            
        };
        
        void buildFooter(Footer& footer)
        {
            buffer.append("  <Footer>
    "); 
            buffer.append("    <ExportUser>"+footer.getUser()+"
    "); 
            buffer.append("  </Footer>
    ");
            buffer.append("</Report>
    ");        
        }
        
        void buildHeader(Header& header)
        {
            buffer.append("<?xml version ='1.0' encoding ='gb2312'?>
    ");
            buffer.append("<Report>
    ");
            buffer.append("  <Header>
    ");
            buffer.append("    <DepId>"+header.getDepId()+"</DepId>
    ");
            buffer.append("    <ExportDate>"+header.getDate()+"</ExportDate>
    ");
            buffer.append("  </Header>
    ");
        }
        
        string& getResult(){return buffer;}
    };
    
    //TxtBuilder
    class TxtBuilder : public Builder
    {
    private:
        string buffer; //用来记录文件的内容,相当于最终产品
    public:
        void buildBody(list<Body>& bodys)
        {
            list<Body>::iterator first = bodys.begin();
            list<Body>::iterator last = bodys.end();
            buffer.append("Sale details:
    ");
            
            ostringstream oss;
            while (first !=  last)
            {
                buffer.append("ProductId="+first->getProductId()+", ");
                
                oss.str("");
                oss << first->getPrice();
                buffer.append("Price=" + oss.str()+", ");
                
                oss.str("");
                oss << first->getAmount();        
                buffer.append("Amount=" + oss.str()+"
    ");
    
                ++first;
            }
        }
        
        void buildFooter(Footer& footer)
        {
            buffer.append(footer.getUser());
        }
        
        void buildHeader(Header& header)
        {
            buffer.append(header.getDepId()+","+header.getDate() + '
    ');
        }
        
        string& getResult(){return buffer;}
    };
    
    //*********************************Director*********************
    class Director
    {
    private:
        Builder* builder;
    public:
        Director(Builder* builder){this->builder = builder;}
        
        void construct(Header& header,list<Body>& bodys,Footer& footer)
        {
            builder->buildHeader(header);
            builder->buildBody(bodys);
            builder->buildFooter(footer);      
        }     
    };
    
    int main()
    {
        //客户端调用例子
     
        //准备测试数据
        Header* header = new Header();
        header->setDepId("one company");
        header->setDate("2016-5-18");
        
        list<Body> bodys;
        
        Body* body1 = new Body();
        body1->setProductId("001");
        body1->setPrice(100);
        body1->setAmount(80);
        
        Body* body2 = new Body();
        body2->setProductId("002");
        body2->setPrice(99);
        body2->setAmount(55);
        
        bodys.push_back(*body1);
        bodys.push_back(*body2);
         
        Footer* footer = new Footer();
        footer->setUser("SantaClaus");
        
        //测试输出到文本文件
        TxtBuilder* txtBuilder = new TxtBuilder();
    
        //创建指导者对象
        Director* directorTxt = new Director(txtBuilder);
        directorTxt->construct(*header,bodys,*footer);
        
        cout << txtBuilder->getResult() << endl;
        
        //测试输出到XML文件
        XmlBuilder* xmlBuilder = new XmlBuilder();
    
        //创建指导者对象
        Director* directorXml = new Director(xmlBuilder);
        directorXml->construct(*header,bodys,*footer);
        
        cout << xmlBuilder->getResult() << endl;
        
        delete txtBuilder;
        delete directorTxt;
        
        delete xmlBuilder;
        delete directorXml; 
    
        delete header;
        delete body1;
        delete body2;
        delete footer;
        
        return 0;
    }
  • 相关阅读:
    cron表达式
    特殊二叉树和平衡二叉树和树的遍历
    进阶之常见算法和算法题
    原码,反码,补码、移码
    PostgreSQL 大小写问题 一键修改表名、字段名为小写
    ImportError: cannot import name 'PackageFinder' from 'pip._internal.index'
    安装pl/sql developer(内附下载地址)
    oracle plsql的结构
    oracle数据库基本操作
    java的高并发IO原理,阻塞BIO同步非阻塞NIO,异步非阻塞AIO
  • 原文地址:https://www.cnblogs.com/5iedu/p/5503775.html
Copyright © 2011-2022 走看看