原型模式是创建型模式。
设计意图:用原型实例指定创建对象的类型,并通过拷贝这个原型来创建新的对象。
我们使用构建简历的例子的类图来说明原型模式。
类图:
原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。这里我们定义了一个抽象的原型接口,声明了用于clone自己的方法,这里我们已创建简历为具体原型类,Prototype类需要具备以下两个条件:
- 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
- 重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。
原型模式是一种比较简单的模式,也非常容易理解,实现一个接口,重写一个方法即完成了原型模式。在实际应用中,原型模式很少单独出现。经常与其他模式混用,他的原型类Prototype也常用抽象类来替代,这里我们在原型类上加了一个接口,该接口类继承的Cloneable接口,这样我们可以在我们自己接口中更灵活的控制具体原型类的逻辑是什么。
package com.prototype;
/**
* @author gaoxu
* 实践出真知!
*/
public interface IPrototype extends Cloneable{
public Prototype clone();
public void show();
}
package com.prototype;
/**原型抽象类,采用原型抽象类,可以使具体原型类有更多的可复用的属性实现
* @author gaoxu
* 实践出真知!
*/
public abstract class Prototype implements IPrototype{
String name = "";
String mobile = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
@Override
public Prototype clone() {
Prototype prototype = null;
try {
prototype = (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return prototype;
}
public String toString(){
return "mobile="+mobile+",name="+name;
}
}
package com.prototype;
/**
* 简历原型实现类
*
* @author gaoxu 实践出真知!
*/
public class Resume extends Prototype {
@Override
public void show() {
System.out.println(""+toString());
}
}
package com.prototype;
/**
* @author gaoxu
* 实践出真知!
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
Resume resume = new Resume();
resume.setName("高旭");
resume.setMobile("1390000111");
Resume resume1 = (Resume) resume.clone();
Resume resume2 = (Resume) resume.clone();
System.out.println(resume.toString());
System.out.println(resume1.toString());
System.out.println(resume2.toString());
}
}
原型模式的优点和适用场景:
最大的优点就是创建对象性能好,比new要快不少,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。所以需要重复创建对象的场景基本都可以适用。
原型模式的注意事项
- 使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,不用重新初始化,直接获得对象运行时的状态。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,所以不能把单例模式的类对象进行拷贝,那样就不是单例了。