代码GitHub:github.com/lanjie6/Des…
原型模式
- 原型模式指的是用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象,在这里。原型实例指定了要创建的对象的种类。
- 用这种方式创建对象非常高效,根本无须知道对象创建的细节。例如,虚拟机CentOS操作系统的安装通常较耗时,如果克隆就快了很多。
进一步阐述:
- 原型模式的克隆分为浅克隆和深克隆。
- 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
- 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
原型模式包含的三种角色:
- AbstractPrototype(抽象原型角色):规定了具体原型对象必须实现的接口。
- ConcretePrototype(具体原型角色):实现抽象原型类的 clone() 方法,它是可被复制的对象。
- Visit(访问角色):使用具体原型类中的 clone() 方法来复制新的对象。
案例:用原型模式生成“三好学生”奖状为例,同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,属于相似对象的复制,然后再做简单修改就可以了。客户端Client类就是具体的访问角色,奖状Citation类,就是具体原型角色,JDK提供的Cloneable接口就是抽象原型角色。
UML类图:
客户端Client类:
/**
* 使用原型模式的客户端(访问角色)
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
//创建奖状原型
Citation citation = new Citation("xx", "同学:在2021学年第一学期中表现优秀,被评为三好学生。", "成都学院");
//克隆奖状,并写上每个同学的姓名
Citation zhangSanCitation= (Citation) citation.clone();
zhangSanCitation.setName("张三");
zhangSanCitation.display();
Citation liSiCitation= (Citation) citation.clone();
liSiCitation.setName("李四");
liSiCitation.display();
}
}
奖状Citation类:
/**
* 奖状类(具体原型角色)
* 其中JDK提供的Cloneable接口就是抽象原型角色
*/
public class Citation implements Cloneable {
/**
* 获奖学生名字
*/
String name;
/**
* 获奖信息
*/
String info;
/**
* 学院
*/
String college;
public Citation(String name, String info, String college) {
this.name = name;
this.info = info;
this.college = college;
System.out.println("奖状创建成功!");
}
/**
* 设置不同学生的奖状名字
*/
public void setName(String name) {
this.name = name;
}
/**
* 陈列奖状信息的方法
*/
public void display() {
System.out.println(name + info + college);
}
/**
* 重写克隆方法
*/
@Override
public Object clone() throws CloneNotSupportedException {
System.out.println("奖状拷贝成功!");
return super.clone();
}
}
运行结果:
总结:
- Java自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
- 需要为每一个类都配置一个 clone 方法,clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
- 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
典型运用场景举例:
- 对象之间相同或相似,即只是个别的几个属性不同的时候。
- 系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值。
- 在 Spring 中,原型模式应用的非常广泛,例如 @scope("prototype")改为多例模式的时候,其实对象是基于原型模式克隆出来的多个对象,并非是New出来和反射出来的。
设计模式相关文章
- 【Java设计模式】设计模式七大基本原则(一)
- 【Java设计模式】创建型设计模式-单例模式(二)
- 【Java设计模式】创建型设计模式-工厂模式(三)
- 【Java设计模式】创建型设计模式-建造者模式(四)
- 【Java设计模式】创建型设计模式-原型模式(五)
- 【Java设计模式】结构型设计模式-适配器模式(六)
- 【Java设计模式】结构型设计模式-装饰者模式(七)
- 【Java设计模式】结构型设计模式-门面模式(八)
- 【Java设计模式】结构型设计模式-桥接模式(九)
- 【Java设计模式】结构型设计模式-代理模式(十)
- 【Java设计模式】结构型设计模式-享元模式(十一)
- 【Java设计模式】结构型设计模式-组合模式(十二)
- 【Java设计模式】行为型设计模式-策略模式(十三)
- 【Java设计模式】行为型设计模式-模板方法模式(十四)
- 【Java设计模式】行为型设计模式-观察者模式(十五)
- 【Java设计模式】行为型设计模式-责任链模式(十六)
- 【Java设计模式】行为型设计模式-委派模式(十七)
- 【Java设计模式】行为型设计模式-状态模式(十八)
- 【Java设计模式】行为型设计模式-中介者模式(十九)
- 【Java设计模式】行为型设计模式-迭代器模式(二十)
- 【Java设计模式】行为型设计模式-访问者模式(二十一)
- 【Java设计模式】行为型设计模式-备忘录模式(二十二)
- 【Java设计模式】行为型设计模式-解释器模式(二十三)