持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情
本文系作者 不太自律的程序猿原创,转载请私信并在文章开头附带作者和原文地址链接。
建造者模式
建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
使用场景
1、资源优化场景。
2、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
3、性能和安全要求的场景。
4、通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
5、一个对象多个修改者的场景。
6、一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
7、在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。
代码演示
原型类代码 重点是实现Cloneable接口以及重写clone方法
public class Prototype implements Cloneable, Serializable {
private String name;
private int age;
private RefObject refObject;
public Prototype(String name, int age) {
this.name = name;
this.age = age;
}
public RefObject getRefObject() {
return refObject;
}
public void setRefObject(RefObject refObject) {
this.refObject = refObject;
}
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;
}
//重写克隆方法 默认浅拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
Prototype clone = (Prototype) super.clone();
return clone;
}
@Override
public String toString() {
return "Prototype{" +
"name='" + name + '\'' +
", age=" + age +
", refObject=" + refObject +
'}';
}
}
客户端 main方法 使用
public static void main(String[] args) throws CloneNotSupportedException {
Prototype prototype = new Prototype("原型模板",10);
prototype.setRefObject(new RefObject());
Prototype clone1 = (Prototype) prototype.clone();
Prototype clone2 = (Prototype) prototype.clone();
System.out.println(clone1);
System.out.println(clone2);
System.out.println("原型 hashCode"+prototype.getRefObject().hashCode());
System.out.println("浅克隆 hashCode"+clone1.getRefObject().hashCode());
System.out.println("浅克隆 hashCode"+clone2.getRefObject().hashCode());
System.out.println(prototype.getRefObject()==clone1.getRefObject());
System.out.println(prototype.getRefObject()==clone2.getRefObject());
}
上面使用的是浅克隆模式,下面使用深克隆模式,修改Prototype的clone方法
//深拷贝 利用反序列 和序列化
@Override
protected Object clone() {
//序列化 将当前对象序列化到内存中
ByteArrayOutputStream byteArrayOutputStream;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
oos = new ObjectOutputStream(byteArrayOutputStream);
oos.writeObject(this);
//反序列化
byte[] bytes = byteArrayOutputStream.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bis);
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
优缺点
优点:
1、Prototype模式允许动态增加或减少产品类。由于创建产品类实例的方法是产批类内部具有的,因此增加新产品对整个结构没有影响。
2、Prototype模式提供了简化的创建结构。工厂方法模式常常需要有一个与产品类等级结构相同的等级结构,而Prototype模式就不需要这样。
3、Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。
4、产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构。
缺点:
每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。
JDK源码中的应用:
1 org.springframework.web.servlet.mvc.method.RequestMappingInfo
2 org.springframework.beans.factory.support.BeanDefinitionBuilder
感谢诸君的观看,文中如有纰漏,欢迎在评论区来交流。如果这篇文章帮助到了你,欢迎点赞👍关注。