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

  • 相关阅读:
    UVa 1354 天平难题 (枚举二叉树)
    广西邀请赛总结
    UVa 12118 检查员的难题 (dfs判连通, 构造欧拉通路)
    UVA
    Uva 127 "Accordian" Patience (模拟)
    UVA 10539 Almost Prime Numbers( 素数因子)
    HDU 1272 小希的迷宫(并查集)
    HDU 1213 How Many Tables (并查集)
    POJ 2236 Wireless Network(并查集)
    HDU 1233 还是畅通工程 ( Kruskal或Prim)
  • 原文地址:https://www.cnblogs.com/jyyzzjl/p/5174203.html
Copyright © 2020-2023  润新知