zoukankan      html  css  js  c++  java
  • [工作中的设计模式]建造者模式builder

    一、模式解析

      建造模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心。

      以上是对建造者模式的官方定义,简单说就是对于复杂对象的创建,由一个建造者封装了对象组件的生成,由专门的指挥者来负责指挥对象生产和组件装配,调用者仅需要通知指挥者建造者进行生产,即可从对象本身获取完整对象。

      要点为:

      1、 模式的主要参与者为:抽象建造者,具体建造者,指挥者。

      2、具体建造者负责具体实施生产

      3、指挥者仅负责提供解决方案和流程

      4、最终的产品创建细节和产品交付由具体建造者负责

    二、模式代码

    定义产品的模块组成

    package build.patten;
    
    /**
     * 产品的组成部分
     * @author zjl
     * @time 2016-1-29
     *
     */
    public class Part {
        public String name;
    
        public Part(String name) {
            super();
            this.name = name;
        }
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return this.name.toString();
        }
    }

    2、定义产品,产品由三个部分组成,因此保存一个组成部分的列表

    package build.patten;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 产品,可以包含A,B,C三个部分
     * @author zjl
     * @time 2016-1-29
     *
     */
    public class Product {
        List<Part> parts=new ArrayList<Part>();
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return parts.toString();
        }
        
    }

    3、抽象的建造者,规定了对产品各部分的建造接口

    package build.patten;
    
    public interface IBuild {
        public void buildPartA();
        public void buildPartB();
        public void buildPartC();
        public Product getResult();
    }

    4、具体建造者,实现抽象建造者的方法,可以有一个或多个

    package build.patten;
    
    public class ConcreteBuild implements IBuild {
        Product product=new Product();
    
        @Override
        public void buildPartA() {
            // TODO Auto-generated method stub
            product.parts.add(new Part("partA"));
        }
    
        @Override
        public void buildPartB() {
            // TODO Auto-generated method stub
            product.parts.add(new Part("partB"));
        }
    
        @Override
        public void buildPartC() {
            // TODO Auto-generated method stub
            product.parts.add(new Part("partC"));
        }
    
        @Override
        public Product getResult() {
            // TODO Auto-generated method stub
            return product;
        }
    
    }

    4、指挥者类,负责告诉建造者,应该以什么样的逻辑完成产品的创建

    package build.patten;
    
    public class Director {
        IBuild build;
        public Director(IBuild build){
            this.build=build;
        }
        
        public void build(){
            this.build.buildPartA();
            this.build.buildPartB();
            this.build.buildPartC();
        }
    }

    5、客户端

    package build.patten;
    
    public class Client {
        public static void main(String[] args) {
            IBuild build=new ConcreteBuild();
            Director director=new Director(build);
            director.build();
            Product product=build.getResult();
            System.out.println(product);
        }
        
    }

    6、运行结果,也就是创建的产品

    [partA, partB, partC]

    三、应用场景

    建造者模式由于需要中间的指挥者来完成对产品各部分的建设,其实在工作中用的还是比较少,不过最近正在装修,似乎可以找到类似的原型:

    在装修的过程中,我们将房子交给装修公司后,由设计师和工人来共同完成对房子的装修,其中设计师负责进行设计,规定房子如何装;具体干活:比如泥工,木工,电工均由工人完成。

    整个装修过程比较复杂,因此我们选取简单的一块,比如门的设计和安装来举例:我的房子是两室一厨一卫,所以共需要四个门,门的牌子和材质可以有不同的选择,设计师负责进行选择,工人仅需要安装即可。

    四、场景代码

    1、定义门,

    package build.example;
    
    public class Door {
        //名称
        public String name;
        //材料
        public String type;
        //位置
        public String pos;
        public Door(String name,String pos){
            this.name=name;
            this.pos=pos;
        }
        
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return pos+"的位置安装厂家为"+name+"的"+type+"门";
        }
    
    }

    定义房子,也就是最终交付的成果

    package build.example;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 房子装修,可以请装修工人对房子进行装修
     * 不同人的房子可能装法不同
     * 假设装修两室一厅,共四个门,厨卫+两个卧室
     * @author zjl
     * @time 2016-1-29
     *
     */
    public class House {
        List<Door> doors=new ArrayList<Door>();
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return doors.toString();
        }
    }

    3、定义工人,工人会装木门,也会装合金门

    package build.example;
    /**
     * 抽象的装修工人,定义了装修工人会的技能
     * 此处仅以装门来考虑
     * @author zjl
     * @time 2016-1-29
     *
     */
    public abstract class AbstractWorker {
    
        public abstract void fixMumen(Door door);
        public abstract void fixHejinmen(Door door);
        public abstract House getHouse();
        
    }

    4、定义一个具体的工人,每个工人手艺不一样,所以可以选择的工人很多,但他们都必须会装门

    package build.example;
    
    public class ConcreteWorkerA extends AbstractWorker {
        public House house=new House();
        @Override
        public House getHouse(){
            return house;
        }
        @Override
        public void fixMumen(Door door) {
            door.type="木";
            house.doors.add(door);
            
        }
    
        @Override
        public void fixHejinmen(Door door) {
            door.type="合金";
            house.doors.add(door);
        }
    
    }

    5、设计师,负责设计门如何安装

    package build.example;
    /**
     * 设计师,负责设计门的的种类和选材
     * @author zjl
     * @time 2016-1-29
     *
     */
    public class Designer {
        AbstractWorker worker;
        public Designer(AbstractWorker worker){
            this.worker=worker;
        }
        public void bulid() {
            worker.fixMumen(new Door("A厂家", "厨房"));
            worker.fixMumen(new Door("A厂家", "厕所"));
            worker.fixHejinmen(new Door("A厂家", "主卧"));
            worker.fixHejinmen(new Door("A厂家", "次卧"));
        }
    
    }

    6、我自己,只负责催进度和要结果

    package build.example;
    
    public class Client {
        public static void main(String[] args) {
            AbstractWorker worker=new ConcreteWorkerA();
            Designer designer=new Designer(worker);
            designer.bulid();
            House house=worker.getHouse();
            System.out.println(house);
        }
    }

    7、生产结果

    [厨房的位置安装厂家为A厂家的木门, 
    厕所的位置安装厂家为A厂家的木门,
    主卧的位置安装厂家为A厂家的合金门,
    次卧的位置安装厂家为A厂家的合金门]

    五、模式疑问

      1、产品的交付,在模式标准中有建造者进行完成,似乎感觉由指挥者直接完成整个产品的返回似乎也可以,具体区别以后补充

      2、指挥者的存在是建造者模式的关键,将顺序剥离了建造者,其实我们完全可以将建造顺序和过程封装到抽象建造者内,此时建造者模式就变成了模板模式。

      3、针对第二点,为什么有了原型模式后,还会有建造者模式,其实建造者模式可以有多个指挥者,不同的指挥者可以设计出不同的建造顺序和逻辑,从而产生出不同的产品,例如我们装修时,找不同的设计师,设计出不同的风格,那么用的材料和牌子也会不同,此时原型模式由于在父类中规定了建造流程,反而无法达到此效果。

  • 相关阅读:
    收录
    查看表结构(数据字段说明等)
    JS 转换日期UTC类型
    Vue项目搭建
    win10 解决端口被占用
    mybatis 生成代码配置 mybatis-generator:generate 的使用详解
    mybatis-generator:generate 生成代码配置踩坑详解
    Spring boot 集成 Druid 数据源
    Spring Boot跨域解决方案
    Sublime Text 实用方法
  • 原文地址:https://www.cnblogs.com/jyyzzjl/p/5174203.html
Copyright © 2011-2022 走看看