美文网首页
来唠唠Java中建造者模式的嗑

来唠唠Java中建造者模式的嗑

作者: 坑逼的严 | 来源:发表于2019-04-18 13:56 被阅读0次

    在Android23种设计模式中,前几章就是建造者模式,可以看出他的简单性与重要性,往往简单常用的设计模式作者才会放在前头,是不?我反正是猜的。
    这书我是对它无语的,看不懂绕来绕去的,


    无奈.jpg

    那怎么办呢?我的眼睛默默瞟向了旁边的架构师,起初他并不不理会我,被我打老实了,然后才“促膝长谈”,下面我把我了解到的和大家分享下。


    嘻嘻.jpg
    我们拿一个建造房子作为比方,我们主要注意四个点:客户-》设计师-》包工头-》设计师的蓝图-》产品房子。数了下,是五个方面,嘻嘻。每一个标准build模式都遵循这几个点,根据不同的产品给出不同的设计师代码,包工头代码,设计师的蓝图就行了。
    开始建造我们的房子,就先来产品,House类,加入一个客户要一个有地基、墙、屋顶的单栋楼的别墅那么我们就定义如下:
    /**
     * 严金
     * 2019-4-18 10:30:21
     * 具体建造的产品
     *
     */
    public class House {
        //地基
        private String foundation;
        //墙
        private String wall;
        //屋顶
        private String roof;
    
        public String getFoundation() {
            return foundation;
        }
    
        public void setFoundation(String foundation) {
            this.foundation = foundation;
        }
    
        public String getWall() {
            return wall;
        }
    
        public void setWall(String wall) {
            this.wall = wall;
        }
    
        public String getRoof() {
            return roof;
        }
    
        public void setRoof(String roof) {
            this.roof = roof;
        }
    }
    

    接下来是设计师的蓝图,为啥叫他蓝图,因为建造行业都有蓝图一次,就是图纸,工人根据这个建造产品,玩过方舟生存进化的玩家都知道里面有好多蓝图,挺好玩的。那么这里的蓝图就是抽象化的了,所以把他定义成一个接口,毕竟他只是图纸,属于设计师的创作,但是真正实现的才是包工头本人,下面是蓝图的代码:

    /**
    * yanjin
    * 2019-4-18 10:24:30
    *
    * 这是标准建造者模式中的抽象建造者
    * 定义着能建造什么
    */
    public interface Build{
       //地基
       void buildFoundation();
       //墙
       void buildWall();
       //屋顶
       void buildRoof();
    
       House getProduct();
    }
    

    上面说到真正建造的人是包工头,那么他肯定是有蓝图上的功能的,

    
    /**
     * yanjin
     * 2019-4-18 10:28:33
     * 这是实现建造功能的具体建造者
     * 它象征着包工头,具体干事情的
     */
    public class BuildeImp implements Build {
        House house = new House();
        @Override
        public void buildFoundation() {
            house.setFoundation("水泥地基");
        }
    
        @Override
        public void buildWall() {
            house.setWall("大理石墙砖");
        }
    
        @Override
        public void buildRoof() {
            house.setRoof("教堂屋顶");
        }
    
        @Override
        public  House getProduct() {
            return  house;
        }
    
    }
    

    可以看到,包工头完全是按蓝图办事的,那么我们都知道,一个包工头能画出蓝图来吗?这显然不是,就像初级程序员不能整个大型项目框架一个样,只能负责搬砖,除非他努力学习,取而代之你们说是不是呢?所以多多学习才是硬道理。这个蓝图肯定是设计师给到的,那么我们看看设计师代码

    public class Designer {
        public Build design(Build build){
            build.buildFoundation();
            build.buildRoof();
            build.buildWall();
            return build;
        }
    }
    

    代码很简单,设计师持有蓝图build,但是干实事的还是包工头BuildeImp,接口编程,这个可以理解吧。
    最后试试客户了,案例来说客户只要调用设计师,设计师拿着蓝图找包工头办事,最后包工头产出产品房子就是了,看看客户代码

    public class Clicent {
        public static void main(String args[]){
            Build build = new BuildeImp();
            Designer designer =new Designer();
            designer.design(build);
            House house = build.getProduct();
            System.out.println("产品:"+house.getFoundation()+"-"+house.getWall()+"-"+house.getRoof());
        }
    }
    

    果然如此,哈哈哈


    哈哈.gif

    变异版本!!!!

    啥叫变异版本?上面刚说包工头不可能画出蓝图,除非他努力,所以变异版本就基于包工头的努力而产生的变化,咸鱼翻身了! 看过AlertDialog源码的都知道,他也是build模式,但是他没有这么死板的遵守,而是去掉了设计师和他的蓝图,中间商赚差价,迟早被干。所以一上来,我们就把上面的设计师代码和Build蓝图代码都删除。删除之后,肯定是报错了,先不管,我们先看看之前房子源码

    /**
     * 严金
     * 2019-4-18 10:30:21
     * 具体建造的产品
     *
     */
    public class House {
        //地基
        private String foundation;
        //墙
        private String wall;
        //屋顶
        private String roof;
    
        public String getFoundation() {
            return foundation;
        }
    
        public void setFoundation(String foundation) {
            this.foundation = foundation;
        }
    
        public String getWall() {
            return wall;
        }
    
        public void setWall(String wall) {
            this.wall = wall;
        }
    
        public String getRoof() {
            return roof;
        }
    
        public void setRoof(String roof) {
            this.roof = roof;
        }
    }
    
    

    这里提供了set和get方法,但是我们原则上是不允许客户能直接对产品动手动脚的,那怎么隔离?直接删除呗,删除完了就只剩下三个私有属性了,那么怎么设置呢?那我们就要提供一个apply方法给别用赋值用,

    /**
     * 严金
     * 2019-4-18 10:30:21
     * 具体建造的产品
     *
     */
    public class House {
        //地基
        private String foundation;
        //墙
        private String wall;
        //屋顶
        private String roof;
    
        public void apply(BuildeImp.BuildeImpParams params) {
            foundation = params.foundation;
            wall = params.wall;
            roof=params.roof;
        }
    
        @Override
        public String toString() {
            return "House{" +
                    "foundation='" + foundation + '\'' +
                    ", wall='" + wall + '\'' +
                    ", roof='" + roof + '\'' +
                    '}';
        }
    }
    

    BuildeImpParams 是包工头自己画的蓝图,所有功能都有他自己完成,这就是包工头的厂库,完成这个房子的所需品都在这个里面,那么他肯定写成内部类是最好的选择。
    BuildeImp又有那么改变呢?
    原本BuildImp代码是这样的

    /**
     * yanjin
     * 2019-4-18 10:28:33
     * 这是实现建造功能的具体建造者
     * 它象征着包工头,具体干事情的
     */
    public class BuildeImp implements Build {
        House house = new House();
        @Override
        public void buildFoundation() {
            house.setFoundation("水泥地基");
        }
    
        @Override
        public void buildWall() {
            house.setWall("大理石墙砖");
        }
    
        @Override
        public void buildRoof() {
            house.setRoof("教堂屋顶");
        }
    
        @Override
        public  House getProduct() {
            return  house;
        }
    
    }
    

    他的这些方法都是设计师的蓝图提供的,去掉后就要打造自己的蓝图,所以第一步建造BuildeImpParams 自己的蓝图,这个里面有的属性和房子类里面有的属性一模一样,一一对应。然后BuildeImpParams 在BuildeImp的构造方法里面初始化,现实中也是如此,一个包工头独揽一个房子项目,肯定一开始就要做好万全准备。
    BuildeImp提供方法对外接收客户对房子属性的意见,然后一一设置到厂库BuildeImpParams 里面。所以整体代码如下:

    /**
     * yanjin
     * 2019-4-18 10:28:33
     * 这是实现建造功能的具体建造者
     * 它象征着包工头,具体干事情的
     */
    public class BuildeImp {
        private BuildeImpParams params = null;
        public BuildeImp(){
            params = new BuildeImpParams();
        }
    
    
        public BuildeImp setFoundation(String foundation) {
            params.foundation = foundation;
            return this;
        }
    
    
        public BuildeImp setWall(String wall) {
            params.wall = wall;
            return this;
        }
    
    
        public BuildeImp setRoof(String roof) {
            params.roof = roof;
            return this;
        }
    
        public House build(){
            House house=new House();
            house.apply(params);
            return house;
        }
    
        class BuildeImpParams{
            //地基
            public String foundation;
            //墙
            public String wall;
            //屋顶
            public String roof;
        }
    }
    

    这里setFoundation、setWall、setRoof为什么返回this,就是为了链式调用,你看人家AlertDialog用起来多爽,就是因为链式调用很舒服啊。
    然后上客户端代码

    public class Clicent {
        public static void main(String args[]){
            BuildeImp build = new BuildeImp().setFoundation("大理石地基").setWall("水泥的枪").setRoof("黄金的屋顶");
            House house = build.build();
            System.out.println("产品:"+house.toString());
    
        }
    }
    

    客户不管包工头怎么建造的,只管房子到手后的属性与设置的一不一样,这也遵循了最少知识原则。


    你奶奶的.jpg

    相关文章

      网友评论

          本文标题:来唠唠Java中建造者模式的嗑

          本文链接:https://www.haomeiwen.com/subject/rtszwqtx.html