【java设计模式】-06原型模式
原型模式简述
定义: 使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象
,也就是通过复制现有对象实例产生新的对象,也就是所谓的“克隆”
实现方式:
1、实现Cloneable接口
Cloneable接口的作用是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
2、重写Object的clone方法
Java中,所有类的父类都是Object类,Object类中有一个clone方法,返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,原型类需要将clone方法的作用域修改为public类型。
原型模式结构
原型模式包含3个角色:
1)Prototype(抽象原型类):声明克隆方法的抽象类或接口,是所有具体原型类的父类
2)ConcretePrototype(具体原型类):实现抽象原型类声明的克隆方法,实现自我克隆的功能
3)Client(客户端):请求原型对象克隆自身从而创建一个新的对象
代码事例
/**
* 抽象原型类
*
* @author kaifeng
* @date 2018/8/26
*/
public abstract class Prototype implements Cloneable {
/**
* 获取名称
*
* @return
*/
public abstract String getName();
/**
* 抽象拷贝方法
*
* @return Object
* @throws CloneNotSupportedException
*/
public abstract Object copy() throws CloneNotSupportedException;
}
/**
* 具体原型类One
*
* @author kaifeng
* @date 2018/8/26
*/
public class ConcretePrototypeOne extends Prototype {
private String name;
public ConcretePrototypeOne(String name) {
this.name = name;
}
/**
* 获取名称
*
* @return
*/
@Override
public String getName() {
return this.name;
}
/**
* 抽象拷贝方法
*
* @return Object
* @throws CloneNotSupportedException
*/
@Override
public Object copy() throws CloneNotSupportedException {
return super.clone();
}
}
/**
* 具体原型类Two
*
* @author kaifeng
* @date 2018/8/26
*/
public class ConcretePrototypeTwo extends Prototype {
private String name;
public ConcretePrototypeTwo(String name) {
this.name = name;
}
/**
* 获取名称
*
* @return
*/
@Override
public String getName() {
return this.name;
}
/**
* 抽象拷贝方法
*
* @return Object
* @throws CloneNotSupportedException
*/
@Override
public Object copy() throws CloneNotSupportedException {
return super.clone();
}
}
/**
* 原型模式测试
*
* @author kaifeng
* @date 2018/8/26
*/
public class ProtoTypeDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Prototype p1 = new ConcretePrototypeTwo("two");
System.out.println(p1.getName());
Prototype p2 = (ConcretePrototypeTwo) p1.copy();
System.out.println(p2.getName());
}
}
优点
1、隐藏了制造新实例的复杂性,使得创建对象就像我们在编辑文档时的复制粘贴一样简单
2、当创建对象的实例较为复杂的时候,使用原型模式可以简化对象的创建过程,通过复制一个已有的实例可以提高实例的创建效率。
缺点
1、由于使用原型模式复制对象时不会调用类的构造方法,所以原型模式无法和单例模式组合使用,因为原型类需要将clone方法的作用域修改为public类型,那么单例模式的条件就无法满足了。
2、Object类的clone方法只会拷贝对象中的基本数据类型,对于数组,引用对象等只能另行拷贝
适用场景
1、如果创建新对象成本较大,我们可以利用已有的对象进行复制来获得。
2、如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占内存不大的时候,也可以使用原型模式配合备忘录模式来应用。相反,如果对象的状态变化很大,或者对象占用的内存很大,那么采用状态模式会比原型模式更好。
3、需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。
深拷贝(克隆)与浅拷贝(克隆)
浅拷贝:
一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深拷贝:
一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。
java 的clone克隆是浅克隆,对于引用对象,克隆出来的对象和原对象中的引用将指向同一个对象。通常实现深克隆的方法是将对象进行序列化,然后再进行反序列化。