折腾Java设计模式之建造者模式
博文原址:折騰Java設(shè)計模式之建造者模式
建造者模式
Separate the construction of a complex object from its representation, allowing the same construction process to create various representations.
將復(fù)雜對象的構(gòu)造與其表現(xiàn)分離,允許相同的構(gòu)造過程用來創(chuàng)建不同的表現(xiàn)。通俗點就是,一個對象創(chuàng)建過程很復(fù)雜,我們將其每項元素創(chuàng)建過程抽離出來,通過相同的構(gòu)造過程可以構(gòu)造出不用的對象。還不懂可以看到如下的UML圖。
建造者模式UML圖
此AbstractPersonBuilder就是如上的相同的構(gòu)造,而不同的表現(xiàn)就是此處的PersonOneBuilder和PersonTwoBuilder兩個相同方式的構(gòu)造器,但是具體的實現(xiàn)是不一樣而構(gòu)造出不同的表現(xiàn)。所以就是相同的構(gòu)造過程而構(gòu)造出不同的對象。
建造者模式角色
抽象建造者(AbstractPersonBuilder或者Builder):抽象類或者接口,復(fù)雜對象的屬性的抽象方法,并不涉及具體的對象部件的創(chuàng)建;
具體建造者(PersonOneBuilder和PersonTwoBuilder):實現(xiàn)抽象建造者,針對不同的業(yè)務(wù),具體化復(fù)雜對象的各部分的創(chuàng)建。 在建造過程完成后,提供產(chǎn)品的實例;
指揮者(Director):調(diào)用具體建造者來創(chuàng)建復(fù)雜對象的各個部分,在指導(dǎo)者中不涉及具體產(chǎn)品的信息,只負(fù)責(zé)保證對象各部分完整創(chuàng)建或按某種順序創(chuàng)建;
具體的產(chǎn)品(Person):需創(chuàng)建的復(fù)雜對象;
建造者模式源碼干貨
源碼地址:請點擊我
在這里我分為三種情況講講建造者模式,第一種是我們最原始的建造者模式來構(gòu)建,第二種是我們在實體對象時會使用的,第三種是我們平常對實體對象最常規(guī)使用方法借助lombok。
第一種建造者模式
使用的真是上面按照角色來建造的方式,稍微比如下的兩種方法負(fù)責(zé)點。
抽象建造者
public abstract class AbstractPersonBuilder {protected Person product = new Person();public abstract void buildName();public abstract void buildAge();public abstract void buildChildren();public Person build() {return product;} }第一個具體建造者
public class PersonOneBuilder extends AbstractPersonBuilder {public void buildName() {product.setName("老one");}public void buildAge() {product.setAge(44);}public void buildChildren() {product.setChildren(Lists.newArrayList("小one"));}}第二個具體建造者
public class PersonTwoBuilder extends AbstractPersonBuilder {public void buildName() {product.setName("老two");}public void buildAge() {product.setAge(55);}public void buildChildren() {product.setChildren(Lists.newArrayList("小two"));}}Person類充當(dāng)產(chǎn)品數(shù)據(jù)
public class Person {private String name;private int age;private List<String> children;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", children=" + children +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public List<String> getChildren() {return children;}public void setChildren(List<String> children) {this.children = children;} }指揮者,指定具體的建造者用來建造對象
public class Director {private AbstractPersonBuilder builder;public Director(AbstractPersonBuilder builder) {this.builder = builder;}public void setBuilder(AbstractPersonBuilder builder) {this.builder = builder;}public Person construct() {builder.buildName();builder.buildAge();builder.buildChildren();return builder.build();} }示例
@Slf4j public class Application {public static void main(String[] args) {Director director = new Director(new PersonOneBuilder());Person person = director.construct();log.info("person的信息:{}", person);director.setBuilder(new PersonTwoBuilder());person = director.construct();log.info("person的信息:{}", person);} }結(jié)果:
第二種建造者模式
第二種方式比上面那種簡單些,因為我們只指定了一種構(gòu)造方式,并且還可以借用第三方工具IDEA+Plugins。
在IDEA中可以搜索
使用方法:
1.找到對應(yīng)需要添加bulid的類通過自動生成快捷鍵可以查看到build
2.根據(jù)自己的風(fēng)格可以定義bulid的名字,各個bulid方法的前綴以及包名,具體bulider如下代碼中。
PersonBuilder用來Person的構(gòu)建者
public final class PersonBuilder {private String name;private int age;private List<String> children;private PersonBuilder() {}public static PersonBuilder builder() {return new PersonBuilder();}public PersonBuilder withName(String name) {this.name = name;return this;}public PersonBuilder withAge(int age) {this.age = age;return this;}public PersonBuilder withChildren(List<String> children) {this.children = children;return this;}public Person build() {Person person = new Person();person.setName(name);person.setAge(age);person.setChildren(children);return person;} }Person類充當(dāng)產(chǎn)品數(shù)據(jù)
public class Person {private String name;private int age;private List<String> children;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", children=" + children +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public List<String> getChildren() {return children;}public void setChildren(List<String> children) {this.children = children;} }示例
@Slf4j public class Application {public static void main(String[] args) {Person wang = PersonBuilder.builder().withAge(40).withName("老王").withChildren(Lists.newArrayList("李一一", "吳老三")).build();log.info("老王的信息:{}", wang);} }結(jié)果如下:
第三種建造者模式
第三種模式相對來說就簡單非常多,因為我們借用的是lombok的@Builder注解。lombok在18.2版本中引入了@SuperBulider注解用來解決@Builder類的繼承不生效的問題。詳細(xì)的使用闊以看我上篇文章 折騰Java設(shè)計模式之模板方法模式
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class Person {private String name;private int age;private List<String> children;} @Slf4j public class Application {public static void main(String[] args) {Person wang = Person.builder().age(40).name("老王").children(Lists.newArrayList("李一一", "吳老三")).build();log.info("老王的信息:{}", wang);} }結(jié)果:
總結(jié)
第二、三種模式在我們經(jīng)常操作像對VO、DO、DTO對象時,常用如此定義。第一種標(biāo)準(zhǔn)的建造者模式,其實本身指揮者這個角色是不關(guān)心具體的產(chǎn)品實現(xiàn)的,相對于是一種解耦,對于如果新增一種建造者實現(xiàn),可以方便擴展,符合開閉原則,但是無獨有偶,實現(xiàn)了上述優(yōu)點后,但是缺點也跟著來,新增了很多類,維護成本高,如果建造者內(nèi)部發(fā)生變更,就不太適合建造者這種模式了。總體而言還是有很多使用場景的。像StringBulider其實也是一種。像之前在spring-boot的spring-cache中的擴展redis緩存的ttl和key名這篇文章中定義的RedisCacheManagerBuilder,以及我們常用的以后要講的Feign的Builder等等。
歡迎關(guān)注
轉(zhuǎn)載于:https://blog.51cto.com/6271727/2378602
總結(jié)
以上是生活随笔為你收集整理的折腾Java设计模式之建造者模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java交换两个Integer-一道无聊
- 下一篇: 缓冲区溢出-基本ROP-ret2sysc