建造者模式
Posted simple-ly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了建造者模式相关的知识,希望对你有一定的参考价值。
1、 建造者模式
1.1、什么是建造者模式
建造者模式是将一个产品的内部表象与产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。
1.1.1、 内部表象
产品通常会有不同的组成成分作为产品的零件。这些零件有可能是对象,也有可能不是对象。不同的产品可以有不同的内部表象,也就是不同的零件。
1.2、结构
- 抽象建造者(Builder)角色:给出一个接口对象,以规范产品对象各个组成成分的建造。通常包含建造方法和返回方法。一般而言,产品有多少零件就有多少建造方法。返回方法把这些零件组装后返回一个结果对象。
- 具体建造者(Concrete Builder)角色:实现抽象建造者角色的接口,给出各个建造方法创建零件的详细过程和结果组装的结果方法。另外,具体建造者角色做具体的建造工作,不为客户端所知。一般每有一个产品类就有一个具体建造者类。
- 导演者(Director)角色:调用具体建造者角色以创建产品对象。与客户端打交道,将客户端创建产品的请求划分为对各个零件的建造请求,这些请求会委派给具体建造者角色。
- 产品(Product)角色:产品便是建造中的复杂对象。一般来说,一个系统中会有多于一个的产品类,而这些产品类并不一定有共同的接口,可以是不相关联的。
1.3、实例代码
产品角色:
/** * 产品角色 */ @Getter @Setter @ToString public class Product { /** * 零件1 */ private PartOne partOne; /** * 零件2 */ private PartTwo partTwo; /** * 零件3 */ private PartThree partThree; }
零件1:
/** * 零件1 */ public class PartOne { }
零件2:
/** *零件2 */ public class PartTwo { }
零件3:
/** * 零件3 */ public class PartThree { } /** * 零件3 */ public class PartThree { }
抽象建造者角色:
/** * 抽象建造者角色 */ public interface Builder { void buildOne(); void buildTwo(); void buildThree(); Product result(); }
具体建造者角色:
/** * 具体建造者角色 */ public class ConcreteBuilder implements Builder { private Product product = new Product(); @Override public void buildOne() { PartOne partOne = new PartOne(); System.out.println("一系列创建partone的逻辑"); product.setPartOne(partOne); } @Override public void buildTwo() { PartTwo partTwo = new PartTwo(); System.out.println("一系列创建parttwo的逻辑"); product.setPartTwo(partTwo); } @Override public void buildThree() { PartThree partThree = new PartThree(); System.out.println("一系列创建partthree的逻辑"); product.setPartThree(partThree); } @Override public Product result(){ return product; } }
导演者角色:
/** * 导演者角色 */ public class Director{ private Builder builder; public Director(){ builder = new ConcreteBuilder(); } public void buildOne() { builder.buildOne(); } public void buildTwo() { builder.buildTwo(); } public void buildThree() { builder.buildThree(); } public Product getProduct() { return builder.result(); } }
客户端:
/** * 客户端 */ public class Client { public static void main(String[] args) { Director director = new Director(); director.buildOne(); System.out.println(director.getProduct()); director.buildTwo(); System.out.println(director.getProduct()); director.buildThree(); System.out.println(director.getProduct()); } }
运行:
类图:
1.4、多产品类:
当有多个产品类时,只需要创建多个具体建造者角色,每个具体建造者角色负责建造对应的产品。类图如下:
然而,由于抽象建造者角色规定了产品的建造方法。所以派生出来的具体建造者类所建造出来的产品也会是一类产品。所以实际上可以改造成这样的结构:
在导演者角色中,将抽象构造者角色作为构造方法的参数,从而使得传入不同的具体建造者能建造出不同的具体产品。
例如手机。小米8出来后,又出了个小米8青春版。这里就可以抽象出一个手机抽象产品,小米8的具体产品角色和小米8青春版的具体产品角色,对应着小米8具体建造者和小米8青春版具体建造者。
1.5、省略相关角色
建造者模式可以省略一些相关角色,变化还是挺多的。
1.5.1、省略抽象建造者角色:
当只有一个具体建造者角色的话,可以省略抽象建造者角色。抽象建造者角色的目的是规范具体建造者角色的行为。当只有一个具体建造者角色的时候,抽象建造者角色就可以去掉了。此时的类图如下:
这时,导演类可以空的构造方法中去初始化一个具体建造者角色。但是这时的导演者角色就显得有点鸡肋了。完全是对具体建造者角色的一个请求的转发。既然也不会再有其他具体建造者角色。那么此时的导演者角色也可以省略了。
1.5.2、省略导演者角色
这样,客户端就直接与具体建造者角色交互。StringBuilder sb = new StringBuilder();这玩意我想应该大家都用过吧。
1.6、什么时候使用
1)生成的产品对象有复杂的内部结构
2) 生成的产品对象的属性相互依赖。建造者模式强制实行一种分步骤进行的建造过程。因此,如果产品对象的一个属性必须依赖另一个属性被赋值后才可以被赋值。
3)在对象创建过程中会使用到系统中的其他一些对象。这些对象在产品对象的创建过程中不易得到。
1.7、小结
建造者模式是创建一个复杂对象的利器。这个复杂对象包含多个子对象。每个子对象的创建都对应一个建造者的方法。这里简化一下,将复杂对象简化为一个实体类,子对象对应实体类中各个属性。那么在建造方法中加入参数,我们就能建造出一个实体类对象。如果我们再特殊化一下,建造方法中的返回值返回建造者本身,那么,我们就能形成一个链式的创建过程。
参考:
《Java与模式》
以上是关于建造者模式的主要内容,如果未能解决你的问题,请参考以下文章