1. 原型模式概述
原型模式用于创建重复的对象,同时又能保证性能。
原型模式也提供了一种创建对象的最佳方式。
(1) 适用情况
利用一个已有的原型对象,快速生成和原型对象一样的实例,并可以进行修改。特别适用于直接创建对象开销很大的场景。
就像是如果有一个模板,就可以快速复制粘贴,而不用每次都花费很大的代价去创建新的对象。
(2) 优点
可以提高性能。
(3) 缺点
需要实现Cloneable接口,并重写clone方法。
2. 原型模式实例
我们需要用原型模式,来得到不同的球。
(1) 先声明抽象类Ball,实现了Cloneable,重写了clone方法
public abstract class Ball implements Cloneable {
protected String type;
protected Ball(String type) {
this.type = type;
}
abstract protected void declare();
@Override
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
(2) 分别实现不同的球类
public class Basketball extends Ball {
public Basketball() {
super("Basketball");
}
@Override
protected void declare() {
System.out.println("我是篮球。");
}
}
public class Football extends Ball {
public Football() {
super("Football");
}
@Override
protected void declare() {
System.out.println("我是足球。");
}
}
(3) 实现用来获取球的克隆对象的Cache类
public class BallCache {
private static Map<String, Ball> balls = new HashMap<>();
public BallCache() {
Basketball basketball = new Basketball();
balls.put("Basketball", basketball);
Football Football = new Football();
balls.put("Football", Football);
}
public Ball getBall(String type) {
return (Ball) balls.get(type).clone();
}
}
(4) 使用原型模式来获取球的实例
public class BallDemo {
public static void main(String[] args) {
BallCache ballCache = new BallCache();
Ball basketBall = ballCache.getBall("Basketball");
basketBall.declare();
Ball Football = ballCache.getBall("Football");
Football.declare();
}
}
运行结果:
3. 一些思考
Cloneable其实只是一个标记接口,而clone方法其实是Object里面的native方法。
当实现了Cloneable接口后,需要重写Object中的clone方法,然后通过类调用clone方法才能克隆成功。
如果不实现这个接口,只重写clone方法的话,会抛出CloneNotSupportedException异常。
拷贝可以分为引用拷贝、浅拷贝和深拷贝。
引用拷贝就是常见的对象赋值操作,两个引用指向堆中同一块内存。
浅拷贝会创建一个新对象,这个新对象会拷贝基本类型以及引用类型的内存地址,而不会拷贝引用的对象。
深拷贝则是完全拷贝了一个新对象,和原对象没有任何关系。
原型模式可以考虑和单例模式以及工厂模式一起使用,使用单例模式创建原型对象,使用原型模式clone出拷贝对象,做定制化修改,然后由工厂模式提供给调用者,岂不美哉?