• 建造者模式


    概述

    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=二根黄瓜的]
    
  • 相关阅读:
    38.Linux驱动调试-根据系统时钟定位出错位置
    37.Linux驱动调试-根据oops的栈信息,确定函数调用过程
    36.Linux驱动调试-根据oops定位错误代码行
    35.Linux-分析并制作环形缓冲区
    34.Linux-printk分析、使用__FILE__, __FUNCTION__, __LINE__ 调试
    arm裸板驱动总结(makefile+lds链接脚本+裸板调试)
    33.Linux-实现U盘自动挂载(详解)
    Android插件化技术——原理篇
    Android插件化(五):OpenAtlasの四大组件的Hack
    Android插件化(4):OpenAtlasの插件的卸载与更新
  • 原文地址:https://www.cnblogs.com/nnxud/p/9892941.html
Copyright © 2020-2023  润新知