• 建造者模式


    业务场景

    在业务代码中构造了一个类,里面有7个字段,需要给构造方法传7个值

    public class Home {
        //门
        private String Door;
        //椅子
        private String Chair;
        //厨房
        private String Kitchen;
        //马桶
        private String Toilet;
        //浴室
        private String Bathroom;
        //书房
        private String Study;
        //游泳池
        private  String SwimmingPoor;
    
        public void setDoor(String door) {
            Door = door;
        }
    
        public void setChair(String chair) {
            Chair = chair;
        }
    
        public void setKitchen(String kitchen) {
            Kitchen = kitchen;
        }
    
        public void setToilet(String toilet) {
            Toilet = toilet;
        }
    
        public void setBathroom(String bathroom) {
            Bathroom = bathroom;
        }
    
        public void setStudy(String study) {
            Study = study;
        }
    
        public void setSwimmingPoor(String swimmingPoor) {
            SwimmingPoor = swimmingPoor;
        }
        public Home(String door, String chair, String kitchen, String toilet, String bathroom, String study, String swimmingPoor) {
            Door = door;
            Chair = chair;
            Kitchen = kitchen;
            Toilet = toilet;
            Bathroom = bathroom;
            Study = study;
            SwimmingPoor = swimmingPoor;
        }
        public Home() {
        }
    }
    

    因为需要建房子,当时我们的类后面经过扩展发展到了15个字段,甚至更多

    private String Door;//门
    private String Chair;  //椅子
    private String Kitchen;  //厨房
    private String Toilet;  //马桶
    private String Bathroom;   //浴室
    private String Study;    //书房
    private  String SwimmingPoor;    //游泳池
    .........
    

    那继续沿用现在的设计思路,构造函数的参数列表会变得很长,代码在可读性和易用性上都会变差。在使用构造函数的时候,我们就容易搞错各参数的顺序,传递进错误的参数值,导致非常隐蔽的 bug。

    Home home=new Home("铁门","摇摇椅","厨房","","",......)
    

    于是乎可能想到使用set方法来解决,可以选择填写或者不填写

            Home home=new Home();
            home.setBathroom("玻璃浴室");
            home.setChair("木椅子");
            home.setDoor("防盗门");
            home.setStudy("书房");
            home.setToilet("");
            home.set....
    

    但问题又来了,如果我们的构造方法需要进行扩展,比如建有的类型的房子,有的参数不需要使用了,又编写新的构造方法,一个参数依赖另外两个参数,比如我设置了房间的大小,长宽这两个属性是互相依赖的。

        public Home(String door, String chair, String kitchen,String width,String height)
        {
            Door = door;
            Chair = chair;
            Kitchen = kitchen;
            Width=width;
            Height=height;
        }
    

    这样很好,可是如果我们参数就是随意更改和搭配的,那么每次都需要我重新编写构造参数,这样还将细节对外暴露了。单纯用构造函数或者set方法无法做到对参数进行约束,对象可能还存在空或者无效。

    建造者模式重构

    例如上面,有很多参数需要我们去搭配修改,用来创建不同的对象方法

    就像建房子,我们不需要去建,只需要把我们的需求告诉建造者,让它去创建,最后我只管得到这个房子去验收。

    建造者接口

    public interface IHome {
             IHome Door(String door);//桌子
             IHome Chair(String chair);  //椅子
             IHome Kitchen(String kitchen);  //厨房
             IHome Toilet(String toilet);  //马桶
             IHome Bathroom(String bathroom);   //浴室
             String getDetail();//详细信息
    }
    

    具体实现的建造者

    public class HomeBuilder implements IHome {
        Home home=new Home();
    
        List<String> list=new ArrayList<>();
        @Override
        public IHome Door(String door) {
            home.setDoor(door);
            list.add(door);
            return  this;
        }
    
        @Override
        public IHome Chair(String chair) {
            home.setChair(chair);
            list.add(chair);
            return  this;
        }
    
        @Override
        public IHome Kitchen(String  kitchen) {
            home.setKitchen(kitchen);
            list.add(kitchen);
            return  this;
        }
    
        @Override
        public IHome Toilet(String  toilet) {
            home.setToilet(toilet);
            list.add(toilet);
            return  this;
        }
    
        @Override
        public IHome Bathroom(String  bathroom) {
            home.setBathroom(bathroom);
            list.add(bathroom);
            return  this;
        }
    
        @Override
        public String getDetail() {
            StringBuilder detail = new StringBuilder();
            for (String s : list) {
                detail.append(s+" ");
            }
            return  detail.toString();
        }
    }
    

    建造者方法

    public class Build {
        //普通出租房
        public  IHome leveZero() {
            return  new HomeBuilder().Chair("塑料椅").Door("塑料门").Kitchen("小厨房");
        }
    
        //红木家庭房子
        public  IHome leveOne() {
            return  new HomeBuilder().Chair("红木椅").Bathroom("浴室").Door("红木门");
        }
    
        //欧式家庭房子
        public  IHome leveTwo() {
            return  new HomeBuilder().Chair("北欧ins椅").Bathroom("露天浴室").Door("北欧ins门").Kitchen("北欧厨房");
        }
    }
    

    测试验证

        public void  test()
        {
            Build build=new Build();
            String detail = build.leveOne().getDetail();
            System.out.println(detail);
    
            String detail2 = build.leveZero().getDetail();
            System.out.println(detail2);
        }
    

    image-20211011165554113

    不同的家具、房间构成了不同的房子,如果将来业务扩展改动影响也不大

    总结

    一些基本东西不会变,而其组合经常变化的时候,就适合用建造者模式,特别是很多字段,很多种组合的时候,这种设计结构模型可以把重复的内容抽象

    工厂模式和建造者模式的区别

    工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。建造者模式是用来创建一种类型的复杂对 象,通过设置不同的可选参数,“定制化”地创建不同的对象。

  • 相关阅读:
    random模块
    时间模块
    内置函数
    装饰器函数
    python基础二
    linux Ubuntu 16.04安装 postgresql
    Winfrom中的几种传值方式
    C#6.0新特性
    Treeview显示磁盘下的文件,并且可操作
    C#,ASP.NET简单的MD5加密,解密
  • 原文地址:https://www.cnblogs.com/cg-ww/p/15394145.html
Copyright © 2020-2023  润新知