1、原型模式的概念
原型模式,英文Prototype Pattern,属于创建型模式。这种模式用于创建可重复的对象,同时又能保证其性能。该模式实现了一个原型接口,该接口用于创建当前对象的克隆,如果直接创建一个对象需要花费的代价比较大时,那么可以采用原型模式进行创建。举个例子,如果一个对象需要在数据库操作之后被创建,我们都知道,数据库的连接是昂贵的资源,频繁的创建和销毁非常不好,那么此时可以先缓存这个对象,在需要该对象时直接返回它的克隆,这样就不用每次在需要这个对象时都频繁的调用数据库了,在一定程度上可以说提高了性能。
2、原型模式的特点
- 返回对象的克隆。
- 实现原型接口,原型接口用于创建当前对象的克隆。
3、关于原型模式
- 使用目的:用原型实例创建对象,克隆原型实例来创建新的对象。
- 解决问题:在运行期间创建和删除原型实例。
- 使用时机:
- 在运行时指定要实例化的类,比如动态装载。
- 当一个系统应该独立于它的产品来进行创建时。
- 为了避免创建一个与产品类平行的工厂类时。
- 保证原型:利用一个已存在的原型实例,来快速生成一个与原型实例一样的实例。
- 原型关键:实现Cloneable接口,覆写clone方法来进行对象的克隆。
4、原型模式的优缺点
优点:
- 提高创建对象时的性能。
- 不用使用构造方法来进行对象的构建。
缺点:
- 必须要实现Cloneable接口。
5、原型模式的使用场景
- 需要对系统资源进行优化时。
- 类的初始化需要消耗过多资源时,比如数据资源、硬件资源等。
- 对性能和安全有要求时。
- 通过new运算符来产生对象非常的繁琐时。
- 当一个对象对应着多个修改者时。
- 当一个对象需要提供给其他对象使用,并且各个调用者都可以对该对象的值进行修改时,可以克隆该对象生成多个副本对象来提供给调用进行修改。
- 原型模式一般不会单独出现,基本都是和工厂模式一起出现,通过clone方法来克隆对象提供给工厂,由工厂方法提供给调用者使用。
6、原型模式的实现
将创建一个抽象类Shape和扩展了Shape类的实体类。然后类ShapeCache,该类把 shape对象存储在一个Hashtable 中,并在请求的时候返回它们的克隆。图示如下:
(1)创建Shape抽象类
创建一个抽象类Shape,该类实现Cloneable接口,如下:
/*
* 抽象类实现Cloneable接口
*/
public abstract class Shape implements Cloneable {
private String id;
protected String type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
/*
* 覆写clone方法
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// 定义一个抽象方法
public abstract void draw();
}
(2)创建Shape类的扩展类
创建几个Shape抽象类的子类,如下:
/*
* 长方形类,Shape类的扩展子类
*/
public class Rectangle extends Shape{
// 构造方法
public Rectangle() {
this.type = "长方形";
}
@Override
public void draw() {
System.out.println("描绘长方矩形!");
}
}
/*
* 正方形,Shape类的子类
*/
public class Square extends Shape{
public Square() {
this.type = "正方形";
}
@Override
public void draw() {
System.out.println("描绘正方形!");
}
}
/*
* 圆形,Shape类的子类
*/
public class Circle extends Shape{
public Circle() {
this.type = "圆形";
}
@Override
public void draw() {
System.out.println("描绘圆形!");
}
}
(3)创建CacheShape类
创建一个CacheShape类,用来提供克隆对象。
/*
* 该类用来提供克隆对象
*/
public class CacheShape {
// 定义一个Hashtable
private static Hashtable<String, Shape> shapeCached = new Hashtable<>();
// 定义一个方法,用于提供Shape原型实例的克隆对象
public static Shape getShape(String id) throws CloneNotSupportedException {
// 从Hashtable中取出对象
Shape cached = shapeCached.get(id);
// 调用clone方法
Object obj = cached.clone();
return (Shape) obj;
}
// 定义一个方法,往Hashtable中存放一些静态数据
public static void initCached() {
Rectangle rectangle = new Rectangle();
rectangle.setId("1");
shapeCached.put(rectangle.getId(), rectangle);
Square square = new Square();
square.setId("2");
shapeCached.put(square.getId(), square);
Circle circle = new Circle();
circle.setId("3");
shapeCached.put(circle.getId(), circle);
}
}
(4)测试
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
// 初始化
CacheShape.initCached();
Shape clone1 = (Rectangle) CacheShape.getShape("1");
System.out.println("当前形状:" + clone1.getType());
clone1.draw();
System.out.println("----------------------------");
Shape clone2 = (Square) CacheShape.getShape("2");
System.out.println("当前形状:" + clone2.getType());
clone2.draw();
System.out.println("----------------------------");
Shape clone3 = (Circle) CacheShape.getShape("3");
System.out.println("当前形状:" + clone3.getType());
clone3.draw();
}
}
6、小结
原型模式属于创建型模式,该模式最大的特点是根据原型实例来生成克隆对象,一般要实现Cloneable接口,覆写clone方法,返回一个克隆的实例,上面的其实属于浅克隆。如果在当前系统中,通过new来产生对象需要付出较大的代价时,使用原型模式来创建是很好的解决方法。