建造者模式适用于创建工具须要很多步骤,但是步骤的顺序没有严格哀求的。
如果一个工具有繁芜的内部构造,可以将繁芜的工具的创建和利用进行分离(如上图所示)。

建造者的角色划分:

去除类型做建筑设计 常用建材

抽象建造者类(Builder):这个接口规定要实现繁芜工具的哪些部分的创建,并不涉及详细的部件工具的创建。
详细建造者类(ConcreteBuilder):实现 Builder 接口,完成繁芜产品的各个部件的详细创建方法。
在布局过程完成后,供应一个方法,返回创建好的卖力产品工具。
产品类(Product):要创建的繁芜工具 (包含多个组成部件).指挥者类(Director):调用详细建造者来创建繁芜工具的各个部分,在辅导者中不涉及详细产品的信息,只卖力担保工具各部分完全创建或按某种顺序创建(客户端一样平常只须要与指挥者进行交互)。

代码案例:

// 产品类:电子邮件public class Email { private String sender; private String receiver; private String subject; private String content; public String getSender() { return sender; } public void setSender(String sender) { this.sender = sender; } public String getReceiver() { return receiver; } public void setReceiver(String receiver) { this.receiver = receiver; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getContent() { return content; } public void setContent(String content) { this.content = content; }}// 建造者接口:电子邮件建造者public interface EmailBuilder { EmailBuilder setSender(String sender); EmailBuilder setReceiver(String receiver); EmailBuilder setSubject(String subject); EmailBuilder setContent(String content); Email build();}// 详细建造者类:电子邮件建造者实现public class EmailBuilderImpl implements EmailBuilder { private Email email; public EmailBuilderImpl() { email = new Email(); } @Override public EmailBuilder setSender(String sender) { email.setSender(sender); return this; } @Override public EmailBuilder setReceiver(String receiver) { email.setReceiver(receiver); return this; } @Override public EmailBuilder setSubject(String subject) { email.setSubject(subject); return this; } @Override public EmailBuilder setContent(String content) { email.setContent(content); return this; } @Override public Email build() { return email; }}// 客户端代码public class Client { public static void main(String[] args) { EmailBuilder emailBuilder = new EmailBuilderImpl(); Email email = emailBuilder.setSender("sender@example.com") .setReceiver("receiver@example.com") .setSubject("Hello") .setContent("This is a test email.") .build(); System.out.println("Email sent from: " + email.getSender()); System.out.println("Email received by: " + email.getReceiver()); System.out.println("Email subject: " + email.getSubject()); System.out.println("Email content: " + email.getContent()); }}

建造者在源码中实现:

在jdk中Stringbuilder,它的append()方法来构建。

在mybatis中 SqlSessionFactoryBuilder通过build()构建一个工具。

其他的源码中也有很多,比如spring中的BeanDefinitionBuilder,cacheBuilder 等等。

原型模式先容

原型模式(Prototype Design Pattern)用一个已经创建的实例作为原型,通过复制该原型工具来创建一个和原型工具相同的新工具。
原型模式的核心在于拷贝原型工具。
已系统中已经存在的一个原型工具为模型,通过内存二进制流进行拷贝,无需再经历工具的初始化过程。
(例如我们知道的,真假孙悟空)

原型模式包含如下角色:

抽象原型类(Prototype):它是声明克隆方法的接口,是所有详细原型类的公共父类,它可以是抽象类也可以是接口.

详细原型类(ConcretePrototype):实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆工具.

客户类(Client):在客户类中,让一个原型工具克隆自身从而创建一个新的工具.由于客户类针对抽象原型类Prototype编程.因此用户可以根据须要选择详细原型类,系统具有较好的扩展性,增加或者更换详细原型类都比较方便.

// 原型接口:定义了创建工具的方法public interface Prototype { Prototype clone();}// 详细原型类:实现了原型接口的详细类public class ConcretePrototype implements Prototype { private String name; public ConcretePrototype(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Prototype clone() { try { return (Prototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } }}// 客户端代码public class Client { public static void main(String[] args) { ConcretePrototype prototype = new ConcretePrototype("Original"); Prototype clonedPrototype = prototype.clone(); System.out.println("Original prototype: " + prototype.getName()); System.out.println("Cloned prototype: " + ((ConcretePrototype) clonedPrototype).getName()); }} 深克隆与浅克隆

根据在复制原型工具的同时是否复制包含在原型工具中引用类型的成员变量 这个条件,原型模式的克隆机制分为两种,即浅克隆(Shallow Clone)和深克隆(Deep Clone)

1.什么是浅克隆

被复制工具的所有变量都含有与原来的工具相同的值,而所有的对其他工具的引用仍旧指向原来的工具(克隆工具与原型工具共享引用数据类型变量)。

public class ConcretePrototype implements Cloneable { public ConcretePrototype() { System.out.println("详细的原型工具创建完成!"); } @Override protected ConcretePrototype clone() throws CloneNotSupportedException { System.out.println("详细的原型工具复制成功!"); return (ConcretePrototype)super.clone(); }} @Test public void test01() throws CloneNotSupportedException { ConcretePrototype c1 = new ConcretePrototype(); ConcretePrototype c2 = c1.clone(); System.out.println("工具c1和c2是同一个工具?" + (c1 == c2)); }

2.什么是深克隆

撤除那些引用其他工具的变量,被复制工具的所有变量都含有与原来的工具相同的值。
那些引用其他工具的变量将指向被复制过的新工具,而不再是原有的那些被引用的工具。
换言之,深复制把要复制的工具所引用的工具都复制了一遍。

public class ConcretePrototype implements Cloneable { private Person person; public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } void show(){ System.out.println("嫌疑人姓名: " +person.getName()); } public ConcretePrototype() { System.out.println("详细的原型工具创建完成!"); } @Override protected ConcretePrototype clone() throws CloneNotSupportedException { System.out.println("详细的原型工具复制成功!"); return (ConcretePrototype)super.clone(); }}public class Person { private String name; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }}@Test public void test02() throws CloneNotSupportedException { ConcretePrototype c1 = new ConcretePrototype(); Person p1 = new Person(); c1.setPerson(p1); //复制c1 ConcretePrototype c2 = c1.clone(); //获取复制工具c2中的Person工具 Person p2 = c2.getPerson(); p2.setName("峰哥"); //判断p1与p2是否是同一工具 System.out.println("p1和p2是同一个工具?" + (p1 == p2)); c1.show(); c2.show(); }

总结原型模式的优点紧张包括以下几点:

优点:

1. 简化工具创建过程:通过复制已有工具来创建新工具,避免了繁芜的布局过程。

2. 提高效率:对付创建繁芜或耗时工具时效率较高,无需重复实行初始化等操作。

3. 方便动态扩展:可以在运行时方便地通过原型工具天生新的实例,具有一定的灵巧性。

其缺陷紧张有:

1. 须要把稳深拷贝和浅拷贝问题:如果不恰当处理可能导致数据不一致等问题。

2. 对原型工具的修正要谨慎:可能会意外影响到基于它创建的所有工具。

3. 增加了系统的繁芜性:在理解和掩护上可能会带来一定难度