美文网首页
java设计模式(三)建造者模式

java设计模式(三)建造者模式

作者: IT废柴 | 来源:发表于2017-12-19 08:59 被阅读0次

开篇废话

周末因懒的原因,停更了两天。今天主要研究建造者模式。畅游各大博客网站,推荐一篇关于建造者模式的博客http://blog.csdn.net/self_study/article/details/51707029,简单明了,条例清晰。如果看不懂我写的,可以尝试去看看别人的。。。

什么是建造者模式

讲建造者模式,这里要提取几个关键词:

  • 复杂对象: 这里简单的体现可以理解为,这里对象的成员数量很多,所以它很复杂。
  • 构建过程: 对成员对象进行赋值,业务逻辑生成等一系列使之成为一个成熟的对象。
  • 表示: 返回这个对象。
  • 构建过程与表示分离: 一般来说,对成员对象的赋值通常在构造函数中,这种方式除了不够灵活之外,还有就是如果成员对象过多,因为构造函数就会显得十分臃肿。所以,我们可以将构建过程(简单的理解为赋值,这里不严谨,只是为了帮助理解概念)封装成独立的方法,然后再返回整个需要的实例对象。

那么建造者模式:就是为了解决生成复杂对象的问题,主要通过将构建过程与表示分离的方法。


如何实现建造者模式

理解了建造者模式后,我们来实现它,就相对简单了。
首先盗图一张:


建造者模式类图

可以看到,这里呈现了四个类,有时候实际开发中会将这个模型进行简化,我们这里先学习理论,因为实际操作时,灵活变动太多了,不适合讲解。但是万变不离其宗,核心思想就是这些。

  • Product,都称这个为产品类,说白了就是我需要生成的类。
  • Builder类,这是一个抽象类或者接口,用来规定构建对象的所需方法。
  • ConcreteBuilder 对builder的抽象方法的实现类,通常对其优化为product的内部类,从而省掉builder的定义。常见的有 AlertDialog.Builder 。
  • Director 调用concrete的方法的类。一般来说,使用的建造者模式时,这个也给省了。

我们先来看一个完整版的。以造汽车为例,现在我们需要一辆,有四个轮子,有四个座椅,有防风玻璃,有方向盘,发动机等等(这里只列举这几样)。

  • 首先我们先看Product类,就是我们要生成的复杂对象,这里就是指小汽车。
public class Car {
    List<String> tyres = new ArrayList<>();
    List<String> carMounts = new ArrayList<>();
    String glass;
    String steeringWheel;
    String engine;

    public void setTyres(String tyres) {
        this.tyres.add(tyres);
    }

    public void setCarMounts(String carMounts) {
        this.carMounts.add(carMounts);
    }

    public void setGlass(String glass) {
        this.glass = glass;
    }

    public void setSteeringWheel(String steeringWheel) {
        this.steeringWheel = steeringWheel;
    }

    public void setEngine(String engine) {
        this.engine = engine;
    }

    public List<String> getTyres() {
        return tyres;
    }

    public List<String> getCarMounts() {
        return carMounts;
    }

    public String getGlass() {
        return glass;
    }

    public String getSteeringWheel() {
        return steeringWheel;
    }

    public String getEngine() {
        return engine;
    }

}

这里可以看到小汽车有五个属性,然后通过setter和getter方法来对属性赋值。

  • 然后我们先看Builder类,这是一个抽象类或者接口,具体使用看情况而定,我今天想用接口表示:
public interface Builder {
    public void buildeTyre(int wheelNumber);
    public void buildCarMounts(int carMountsNumber);
    public void buildGalss();
    public void buildSteeringWheel();
    public void buildEngine();
    public Car build();
}

这里定义了五个造小汽车零件的方法,和一个生成对象方法,因为你不能只造这些零件,还需要把这些零件给组装起来啊。

  • 紧接着我们需要ConcreteBuilder类来实现这些方法啊,毕竟我们是实干家,不能光说不做!concretebuilder
public class CarBuilder implements Builder {
    
    Car car = new  Car();
    @Override
    public void buildeTyre(int wheelNumber) {
        for (int i = 0; i < wheelNumber; i++) {
            car.setTyres("已经造了" + i + "轮子了");
        }
    }

    @Override
    public void buildCarMounts(int carMountsNumber) {
        for (int i = 0; i < carMountsNumber; i++) {
            car.setCarMounts("已经造了" + i + "椅子了");
        }
    }

    @Override
    public void buildGalss() {
        car.setGlass("防风玻璃做好了");
    }

    @Override
    public void buildSteeringWheel() {
        car.setSteeringWheel("方向盘做好了");
    }

    @Override
    public void buildEngine() {
        car.setEngine("发动机已经做好了");
    }

    @Override
    public Car build() {
        return car;
    }

}

这里实现了builder接口,没什么好说的,值得注意的就是,在CarBuilder类中,维护了一个Car对象,实现的所有方法中,去调用Car的set方法,最后build()方法中去返回这个对象。
此时此刻,我们已经能通过CarBuilder类去建造我们所需要的Car对象了。但是毕竟造汽车的工序是及其复杂了,因为我们这里只简单的列举了五项,可能感觉还是比较轻松的,但是,如果有上百道工序的话,难道我们需要每次去造小车的时候都去调用这上百个方法吗。显然,这里构建的过程,我们希望是不透明的,那么我们可以将这个步骤封装起来,于是就有了Director类的出现。

  • 我们希望有一个技术总工来调度负责整个造车的过程。
public class AodiDirecter {
    private Builder builder;

    public AodiDirecter(Builder builder) {
        this.builder = builder;
    }

    public void construct() {
        builder.buildeTyre(4);
        builder.buildCarMounts(4);
        builder.buildEngine();
        builder.buildGalss();
        builder.buildSteeringWheel();
    }
}

这样整个建造者模式就完成了,而我们需要一个奥迪车时,只需要:

public class Buyer {
    public void buy() {
        Builder builder = new CarBuilder();
        AodiDirecter director = new AodiDirecter(builder);
        director.construct();
        Car aodiCar = builder.build();
    }
}

如果说,builder是产线工人们,AodiDirecter 就可以理解为奥迪工程师,工人们只知道制造器件,工程师来统筹设计造车的工序,安排下去后,工人们按命令执行就行了。而对于买家来说,我并看不到你是怎么造的,反正我只要结果就行了。


但是这样往往会很麻烦,我们通常会对其进行精简优化。

看上面对建造者定义了四个功能模块,在实现过程中,是不是有一些,何必多此一举的感觉。这里我盗用了别人的代码,工作繁忙(太懒了)还请谅解。

public class Computer {
    private String CPU;
    private String GPU;
    private String memoryType;
    private int memorySize;
    private String storageType;
    private int storageSize;
    private String screenType;
    private float screenSize;
    private String OSType;

    public static class Builder {
        // Optional parameters - initialize with default values
        private String CPU = "inter-i3";
        private String GPU = "GTX-960";
        private String memoryType = "ddr3 1666MHz";
        private int memorySize = 8;//8GB
        private String storageType = "hdd";
        private int storageSize = 1024;//1TB
        private String screenType = "IPS";
        private float screenSize = 23.8f;
        private String OSType = "Windows 10";

        public Builder() {
        }

        public Builder setCPU(String CPU) {
            this.CPU = CPU;
            return this;
        }

        public Builder setGPU(String GPU) {
            this.GPU = GPU;
            return this;
        }
        public Builder setMemoryType(String memoryType) {
            this.memoryType = memoryType;
            return this;
        }

        public Builder setMemorySize(int memorySize) {
            this.memorySize = memorySize;
            return this;
        }
        public Builder setStorageType(String storageType) {
            this.storageType = storageType;
            return this;
        }

        public Builder setStorageSize(int storageSize) {
            this.storageSize = storageSize;
            return this;
        }

        public Builder setScreenType(String screenType) {
            this.screenType = screenType;
            return this;
        }
        public Builder setScreenSize(float screenSize) {
            this.screenSize = screenSize;
            return this;
        }

        public Builder setOSType(String OSType) {
            this.OSType = OSType;
            return this;
        }


        public Computer create() {
            return new Computer(this);
        }

    }

    private Computer(Builder builder) {
        CPU = builder.CPU;
        GPU = builder.GPU;
        memoryType = builder.memoryType;
        memorySize = builder.memorySize;
        storageType = builder.storageType;
        storageSize = builder.storageSize;
        screenType = builder.screenType;
        screenSize = builder.screenSize;
        OSType = builder.OSType;
    }
}

可以看到,整个建造者模式就是一个类,然而这个类中存在一个静态内部类Builder,这个Builder,其实对应的是建造者模式中的concreteBuilder,Computer对应的就是我们product。去掉了Builder抽象类,因为直接实现了。同时还缺少了Directer,因为这里的设计是暴露构建细节,所以就不需要了。
这种方式的好处就是,过程可控。我们来看看调用。

Computer computer = new Computer.Builder()
        .setCPU("inter-skylake-i7")
        .setGPU("GTX-Titan")
        .setMemoryType("ddr4-2133MHz")
        .setMemorySize(16)
        .setStorageType("ssd")
        .setStorageSize(512)
        .setScreenType("IPS")
        .setScreenSize(28)
        .setOSType("Ubuntu/Window10")
        .create();

这是一种链式调用,也是我们常见的建造者模式。我们可以对每个成员对象进行控制,从而得到我们想要的product。当然,我们看回Computer类的实现,发现,每个成员对象都是有个默认值的。也就是说,你完全可以通过new Computer.Builder().create()来获取默认的实例对象,这基本就是Directer的功能。所以精简下来,发现建造者模式还是挺实用的。
然而在大型的系统中,精简版的建造者模式,并不是很适用,因为它的针对性太强,往往呈现出来的是同一种产品,拓展性并不是很好,而我们使用原始版的话,可以对Directer进行拓展,可以更加多元灵活。

相关文章

  • 设计模式

    Java 设计模式情景分析 ——单例模式 Java 设计模式情景分析——建造者模式 Java 设计模式情景分析——...

  • Android中涉及的模式

    我的Java设计模式-建造者模式 我的Java设计模式-观察者模式 重学设计模式之单例模式

  • Java设计模式教程

    Java设计模式教程 Java工厂设计模式 Java抽象工厂模式 Java单例模式 Java建造者(Builder...

  • java建造者模式

    其他设计模式java单例模式java建造者模式java策略模式java代理模式java观察者模式java适配器模式...

  • java单例模式

    其他设计模式java单例模式java建造者模式java策略模式java代理模式java观察者模式java适配器模式...

  • java外观模式

    其他设计模式java单例模式java建造者模式java策略模式java代理模式java观察者模式java适配器模式...

  • java适配器模式

    其他设计模式java单例模式java建造者模式java策略模式java代理模式java观察者模式java适配器模式...

  • java观察者模式

    其他设计模式java单例模式java建造者模式java策略模式java代理模式java观察者模式java适配器模式...

  • java代理模式

    其他设计模式java单例模式java建造者模式java策略模式java代理模式java观察者模式java适配器模式...

  • java策略模式

    其他设计模式java单例模式java建造者模式java策略模式java代理模式java观察者模式java适配器模式...

网友评论

      本文标题:java设计模式(三)建造者模式

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