zoukankan      html  css  js  c++  java
  • 设计模式-建造者模式

    传送 http://www.cnblogs.com/BeyondAnyTime/archive/2012/07/19/2599980.html

    一个人活到70岁以上,都会经历这样的几个阶段:婴儿,少年,青年,中年,老年。并且每个人在各个阶段肯定是不一样的呀,我觉得可以说世界上不存在两个人在人生的这5个阶段的生活完全一样,但是活到70岁以上的人,都经历了这几个阶段是肯定的。实际上这是一个比较经典的建造者模式的例子了。

    1.初识建造者模式

    建造者模式实际上是常用的设计模式。顾名思义,builder的意思是建造者或者建筑工人,谈到建造自然会想到楼房。楼房是千差万别的,楼房的外形、层数、内部房间的数量、房间的装饰等等都不一样,但是对于建造者来说,抽象出来的建筑流程是确定的,往往建筑一座楼房包括下面的步骤:(1)打桩,建立基础(2)建立框架等。建造者模式的本质和建造楼房是一致的:即流程不变,但每个流程实现的具体细节则是经常变化的。建造者模式的好处就是保证了流程不会变化,流程即不会增加、也不会遗漏或者产生流程次序错误,这是非常重要的。我们熟知的楼歪歪事件,官方的解释就是由于先建立楼房后,再建设停车场造成的,这是典型的建造次序错乱。(看来这些人儿不知道建造者模式啊!!!)

    我生活的地方有一个菜叫“锅包肉”。基本每个餐馆都有,但是每个餐馆的味道都不一样,原因是什么呢?因为这道菜的作法没有形成标准呗!每个人的作法都不一样,所以味道就不一样了。这实际上通过“建造者模式”让每个馆子的“锅包肉”都一样。同样的KFC做出来的东西,不论是全国哪家店做出来就都一个味,因为KFC内部有很严格的规定,做巨无霸有做巨无霸的流程,必须严格遵守,这样做出来的东西当然一致了。KFC就是采用了建造者模式!!

    说了这么多,到底什么是建造者模式呢?这么神奇。看看GoF怎么说。

                                                          建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

    建造者模式通常包括下面几个角色:

    1. builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。

    2. ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。

    3. Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。

    4. Product:要创建的复杂对象。

      按照惯例,还是给出建造者模式的结构图

                      

    2.一个建造者模式例子实现

      不妨就实现《大话设计模式》上的建造小人的例子吧!!在游戏开发中建造小人是经常的事了,要求是:小人必须包括,头,身体,手和脚。现在系统要包括的分为胖人和瘦人。写出建造者模式的代码如下:

     C++

    #include <iostream>
    #include <vector>
    #include <string>
     
    using namespace std;
    //Product类
    class Product
    {
        vector<string> parts;
    public:
        void Add(const string part)
        {
            parts.push_back(part);
        }
        void Show()const
        {
            for(int i = 0 ; i < parts.size() ; i++)
            {
                cout<<parts[i]<<endl;
            }
        }
    };
    //抽象builder类
    class Builder
    {
    public:
        virtual void BuildHead() = 0;
        virtual void BuildBody() = 0;
        virtual void BuildHand() = 0;
        virtual void BuildFeet() = 0;
        virtual Product GetResult() = 0; 
    };
    //具体胖人创建类
    class FatPersonBuilder :public Builder
    {
    private:
        Product product;
    public:
        virtual void BuildHead()
        {
            product.Add("胖人头");//创建瘦人的头
        }
        virtual void BuildBody()
        {
            product.Add("胖人身体");//创建瘦人的身体
        }
        virtual void BuildHand()
        {
            product.Add("胖人手");//创建瘦人的手
        }
        virtual void BuildFeet()
        {
            product.Add("胖人脚");//创建瘦人的脚
        }
        virtual Product GetResult()
        {
            return product;
        }
    };
    //具体瘦人人创建类
    class ThinPersonBuilder :public Builder
    {
    private:
        Product product;
    public:
        virtual void BuildHead()
        {
            product.Add("瘦人人头");//创建瘦人的头
        }
        virtual void BuildBody()
        {
            product.Add("瘦人身体");//创建瘦人的身体
        }
        virtual void BuildHand()
        {
            product.Add("瘦人手");//创建瘦人的手
        }
        virtual void BuildFeet()
        {
            product.Add("瘦人脚");//创建瘦人的脚
        }
        virtual Product GetResult()
        {
            return product;
        }
    };
    //Director类
    class Director
    {
    public:
        void Construct(Builder &builder)
        {
            builder.BuildHead();
            builder.BuildBody();
            builder.BuildHand();
            builder.BuildFeet();
        }
    };
    
    int main()
    {
        Director *director = new Director();
        Builder *b1 = new FatPersonBuilder();
        Builder *b2 = new ThinPersonBuilder();
    
        director->Construct(*b1);
        Product p1 = b1->GetResult();
        p1.Show(); 
        return 0;
    }
    View Code

    JAVA

    package com.mystyle.建造者模式;
    import java.util.*;
    class product{
        private ArrayList<String> sequence=new ArrayList<String>();
        public void Add(String part){
             this.sequence.add(part);
        }
        public void show(){
             for(int i=0; i<sequence.size(); ++i)
                 System.out.println(sequence.get(i));
        }
        
    }
    abstract class Builder{
           abstract void Buildhead();
           abstract void BuildBody();
           abstract void BuildHand();
           abstract void BuildFeet();
           abstract product GetResult();
    }
    class FatBuilder extends Builder{
          product p = new product();    
        @Override
           protected void Buildhead(){
              p.Add("胖人头");
            }
        @Override
            void BuildBody(){
             p.Add("胖人身体");
        }
        @Override
            void BuildHand(){
               p.Add("胖人手");
        }
        @Override
            void BuildFeet(){
              p.Add("胖人脚");
        }
        @Override
            product GetResult(){
              return this.p;   
           }
        
    }
    class ThinBuilder extends Builder{
          product p = new product();    
        @Override
           protected void Buildhead(){
              p.Add("瘦人头");
            }
        @Override
            void BuildBody(){
             p.Add("瘦人身体");
        }
        @Override
            void BuildHand(){
               p.Add("瘦人手");
        }
        @Override
            void BuildFeet(){
              p.Add("瘦人脚");
        }
        @Override
            product GetResult(){
              return this.p;   
           }
        
    }
    class Director{
         public void Construct(Builder P){
              P.Buildhead();
              P.BuildBody();
              P.BuildHand();
              P.BuildFeet();
         }
    }
    public class example {
          public static void main(String[] arg){
               Director P=new Director();
               FatBuilder F=new FatBuilder();
               ThinBuilder T=new ThinBuilder();
               P.Construct(F);
               product d=F.GetResult(); 
               d.show();
               P.Construct(T);
               d=F.GetResult();
               d.show();
          }
    }
    View Code

    看过上面代码发现使用建造者模式有什么好处了吗?上面的例子,通过建造者模式,使得建造过程通过Director类的Construct函数固定了,即建造过程不会变,也就是满足上面要求中红色字体的“必须包括”。但是具体的头,身体,手脚这些身体的各个部分会变化,基类Builder中将各种Build函数定义为抽象方法,必须在子类中实现。这样不仅仅使得建造小人的过程不变,而且很利于系统的扩展,一旦出现其他种类的人根本不需要改动之前的FatPersonBuider,ThinPersonBuilder,Director,Product等类,只需要新添加新的类。符合OCP原则。

    到这里不知道大家有没有这样的疑问,建造者模式和工厂模式非常相似啊,确实是非常的相似,建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程。两者也有结合使用:比如众神造人,女娲利用建造者模式负责把灵魂、耳目、手臂等组合成一个完整的人,而皇帝、桑林等人各自利用工厂方法模式创造出灵魂,耳目,手臂等。女娲不必考虑灵魂、耳目、手臂是什么样子的,怎么创造出来的,这就成为了一个由建造者模式和工厂方法模式组合而成的系统。

    3.使用建造者模式的场合和好处

    使用建造者模式的好处:

    1.使用建造者模式可以使客户端不必知道产品内部组成的细节。

    2.具体的建造者类之间是相互独立的,对系统的扩展非常有利。

    3.由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

    使用建造模式的场合:

    1.创建一些复杂的对象时,这些对象的内部组成构件间的建造顺序是稳定的,但是对象的内部组成构件面临着复杂的变化。

    2.要创建的复杂对象的算法,独立于该对象的组成部分,也独立于组成部分的装配方法时。

                                                                                                  学习中的一点总结,欢迎拍砖哦

  • 相关阅读:
    LeetCode 1110. Delete Nodes And Return Forest
    LeetCode 473. Matchsticks to Square
    LeetCode 886. Possible Bipartition
    LeetCode 737. Sentence Similarity II
    LeetCode 734. Sentence Similarity
    LeetCode 491. Increasing Subsequences
    LeetCode 1020. Number of Enclaves
    LeetCode 531. Lonely Pixel I
    LeetCode 1091. Shortest Path in Binary Matrix
    LeetCode 590. N-ary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/Opaser/p/4158451.html
Copyright © 2011-2022 走看看