建造者模式

Posted nnxud

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了建造者模式相关的知识,希望对你有一定的参考价值。

概述

Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种。Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。

意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
如何解决:将变与不变分离开。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
应用实例: 1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。 2、JAVA 中的 StringBuilder。
优点: 1、建造者独立,易扩展。 2、便于控制细节风险。
缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。
使用场景: 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

举个例子理解

我们要生产一个Hamburger,假设需要黄油、芥末、番茄酱、沙拉酱、洋葱、黄瓜这些原材料。下面模拟这个生产过程

//Hamburger类

package com.xnn;

/**
 * 类(接口)描述:
 * @author xnn
 * 2018年11月1日下午6:19:51
 */
public class Hamburger {
    //黄油
    private String grease;
    //芥末
    private String mustard;
    //番茄酱
    private String redeye;
    //沙拉酱
    private String mayonnaise;
    //洋葱
    private String onion;
    //黄瓜
    private String  cucumber;
    /**
     * @return the grease
     */
    public String getGrease() {
        return grease;
    }
    /**
     * @param grease the grease to set
     */
    public void setGrease(String grease) {
        this.grease = grease;
    }
    /**
     * @return the mustard
     */
    public String getMustard() {
        return mustard;
    }
    /**
     * @param mustard the mustard to set
     */
    public void setMustard(String mustard) {
        this.mustard = mustard;
    }
    /**
     * @return the redeye
     */
    public String getRedeye() {
        return redeye;
    }
    /**
     * @param redeye the redeye to set
     */
    public void setRedeye(String redeye) {
        this.redeye = redeye;
    }
    /**
     * @return the mayonnaise
     */
    public String getMayonnaise() {
        return mayonnaise;
    }
    /**
     * @param mayonnaise the mayonnaise to set
     */
    public void setMayonnaise(String mayonnaise) {
        this.mayonnaise = mayonnaise;
    }
    /**
     * @return the onion
     */
    public String getOnion() {
        return onion;
    }
    /**
     * @param onion the onion to set
     */
    public void setOnion(String onion) {
        this.onion = onion;
    }
    /**
     * @return the cucumber
     */
    public String getCucumber() {
        return cucumber;
    }
    /**
     * @param cucumber the cucumber to set
     */
    public void setCucumber(String cucumber) {
        this.cucumber = cucumber;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "Hamburger [grease=" + grease + ", mustard=" + mustard
                + ", redeye=" + redeye + ", mayonnaise=" + mayonnaise
                + ", onion=" + onion + ", cucumber=" + cucumber + "]";
    }
    
}


//客户端

package com.xnn;


/**
 * 类(接口)描述:
 * @author xnn
 * 2018年11月1日下午6:15:52
 */
public class MainClass {
public static void main(String[] args) {
    Hamburger hamburger = new Hamburger();
    hamburger.setCucumber("一根黄瓜");
    hamburger.setGrease("一两黄油");
    /**
     * .............................这样造对象甚是麻烦,如果属性再多一点,代码量更大,就算提供全参构造器,那也会造成参数很长
     */
    //这样写,客户端代码省去了很多
    /*BuilderHamburgerImpl builderHamburgerImpl = new BuilderHamburgerImpl();
    BuilderHamburgerImpl1 builderHamburgerImpl1 = new BuilderHamburgerImpl1();
    Directer directer = new Directer();
    Hamburger createHamburger = directer.CreateHamburger(builderHamburgerImpl);
    System.out.println(createHamburger);
    Hamburger createHamburger2 = directer.CreateHamburger(builderHamburgerImpl1);
    System.out.println(createHamburger2);*/
    
}
}

下面用建造者模式去写

Hanburger类
package com.xnn;

/**
 * 类(接口)描述:
 * @author xnn
 * 2018年11月1日下午6:19:51
 */
public class Hamburger {
    //黄油
    private String grease;
    //芥末
    private String mustard;
    //番茄酱
    private String redeye;
    //沙拉酱
    private String mayonnaise;
    //洋葱
    private String onion;
    //黄瓜
    private String  cucumber;
    /**
     * @return the grease
     */
    public String getGrease() {
        return grease;
    }
    /**
     * @param grease the grease to set
     */
    public void setGrease(String grease) {
        this.grease = grease;
    }
    /**
     * @return the mustard
     */
    public String getMustard() {
        return mustard;
    }
    /**
     * @param mustard the mustard to set
     */
    public void setMustard(String mustard) {
        this.mustard = mustard;
    }
    /**
     * @return the redeye
     */
    public String getRedeye() {
        return redeye;
    }
    /**
     * @param redeye the redeye to set
     */
    public void setRedeye(String redeye) {
        this.redeye = redeye;
    }
    /**
     * @return the mayonnaise
     */
    public String getMayonnaise() {
        return mayonnaise;
    }
    /**
     * @param mayonnaise the mayonnaise to set
     */
    public void setMayonnaise(String mayonnaise) {
        this.mayonnaise = mayonnaise;
    }
    /**
     * @return the onion
     */
    public String getOnion() {
        return onion;
    }
    /**
     * @param onion the onion to set
     */
    public void setOnion(String onion) {
        this.onion = onion;
    }
    /**
     * @return the cucumber
     */
    public String getCucumber() {
        return cucumber;
    }
    /**
     * @param cucumber the cucumber to set
     */
    public void setCucumber(String cucumber) {
        this.cucumber = cucumber;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "Hamburger [grease=" + grease + ", mustard=" + mustard
                + ", redeye=" + redeye + ", mayonnaise=" + mayonnaise
                + ", onion=" + onion + ", cucumber=" + cucumber + "]";
    }
    
}


package com.xnn;

/**
 * 类(接口)描述:创建Hamburger的接口,里面声明了创建Hamburger所需要的各种原料的方法,以及创建一个完整Hamburger的方法
 * @author xnn
 * 2018年11月1日下午6:49:13
 */
public interface IBuilderHamburger {
    
    //创建黄油
    public void builderGrease();
    //创建芥末
    public void builderMustard();
    //创建番茄酱
    public void builderRedeye();
    //创建沙拉酱
    public void mayonnaise();
    //创建洋葱
    public void builderOnion();
    //创建黄瓜
    public void builderCucumber();
    //创建汉堡包
    public Hamburger createHamburger();
    
}



package com.xnn;

/**
 * 类(接口)描述:IBuilderHamburger接口的具体实现类,负责创建具体的Hamburger
 * @author xnn
 * 2018年11月1日下午6:57:13
 */
public class BuilderHamburgerImpl implements IBuilderHamburger{
    
      private Hamburger hamburger;
     //在构造方法中创建出一个hamburger对象
    public BuilderHamburgerImpl() {
        super();
        hamburger = new Hamburger();
    }


    public void builderGrease() {
        hamburger.setGrease("一两黄油的");
    }

    
    public void builderMustard() {
        hamburger.setMustard("一两芥末的");
    }

    
    public void builderRedeye() {
        hamburger.setRedeye("一两番茄酱的");
    }

    public void mayonnaise() {
        hamburger.setMayonnaise("一两沙拉酱的");
    }

    
    public void builderOnion() {
        hamburger.setOnion("一个洋葱的");    
        }

    public void builderCucumber() {
        hamburger.setCucumber("一根黄瓜的");
    }

    
    public Hamburger createHamburger() {
        System.out.println("创造出来了一个原料全是一两的hamburger");
        return hamburger;
    }
 
}



package com.xnn;

/**
 * 类(接口)描述:IBuilderHamburger接口的另一个具体实现类,负责创建具体的Hamburger
 * @author xnn
 * 2018年11月1日下午8:07:26
 */
public class BuilderHamburgerImpl1 implements IBuilderHamburger {
    private Hamburger hamburger;
   //在构造方法中创建出一个hamburger对象
    public BuilderHamburgerImpl1() {
        super();
        hamburger = new Hamburger();
    }


    public void builderGrease() {
        hamburger.setGrease("二两黄油的");
    }

    
    public void builderMustard() {
        hamburger.setMustard("二两芥末的");
    }

    
    public void builderRedeye() {
        hamburger.setRedeye("二两番茄酱的");
    }

    public void mayonnaise() {
        hamburger.setMayonnaise("二两沙拉酱的");
    }

    
    public void builderOnion() {
        hamburger.setOnion("二个洋葱的");    
        }

    public void builderCucumber() {
        hamburger.setCucumber("二根黄瓜的");
    }

    
    public Hamburger createHamburger() {
        System.out.println("创造出来了一个原料全是二两的hamburger");
        return hamburger;
    }
}



package com.xnn;


/**
 * 类(接口)描述:客户端类
 * @author xnn
 * 2018年11月1日下午6:15:52
 */
public class MainClass {
public static void main(String[] args) {
    /*Hamburger hamburger = new Hamburger();
    hamburger.setCucumber("一根黄瓜");
    hamburger.setGrease("一两黄油");*/
    /**
     * .............................这样造对象甚是麻烦,如果属性再多一点,代码量更大
     */
    //这样写,客户端代码省去了很多,隐藏了很多创建对象的细节。
    BuilderHamburgerImpl builderHamburgerImpl = new BuilderHamburgerImpl();
    BuilderHamburgerImpl1 builderHamburgerImpl1 = new BuilderHamburgerImpl1();
    Directer directer = new Directer();
    Hamburger createHamburger = directer.CreateHamburger(builderHamburgerImpl);
    System.out.println(createHamburger);
    Hamburger createHamburger2 = directer.CreateHamburger(builderHamburgerImpl1);
    System.out.println(createHamburger2);
    
}
}

运行结果:

创造出来了一个原料全是一两的hamburger
Hamburger [grease=一两黄油的, mustard=一两芥末的, redeye=一两番茄酱的, mayonnaise=null, onion=一个洋葱的, cucumber=一根黄瓜的]
创造出来了一个原料全是二两的hamburger
Hamburger [grease=二两黄油的, mustard=二两芥末的, redeye=二两番茄酱的, mayonnaise=null, onion=二个洋葱的, cucumber=二根黄瓜的]









以上是关于建造者模式的主要内容,如果未能解决你的问题,请参考以下文章

建造者模式(Builder)

设计模式之建造者模式

第十三章-建造者模式

设计模式 创建者模式 -- 建造者模式

设计模式从青铜到王者第八篇:创建型模式之建造者模式(BuilderPattern)

Java设计模式-建造者模式