Java设计模式四:原型模式

  原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。

一、定义与特点

  原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

  这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

  • 原型模式通常适用于以下场景
    1、对象之间相同或相似,即只是个别的几个属性不同的时候。
    2、对象的创建过程比较麻烦,但复制比较简单的时候。
    3、资源优化、性能和安全要求的场景。
    4、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
    5、产生一个对象需要非常繁琐的数据准备或访问权限。
    6、一个对象多个修改者的场景。
    7、一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时。

二、实现方式

(1)创建抽象类

  创建一个抽象类,实现Cloneable接口。

/**
 * 形状抽象类
 */
public abstract class Shape implements Cloneable {

	public Shape(String type) {
		this.type = type;
	}

	private Integer id;

	// 类型
	protected String type;

	// 绘制图制
	abstract void draw();

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	@Override
	public Object clone() {
		Object object = null;
		try {
			object = super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return object;
	}
}

(2)创建实体类

  创建实体类,继承抽象类,并实现其抽象方法。

/**
 * 方形
 */
public class Rectangle extends Shape {

	public Rectangle() {
		super("This is a Rectangle.");
	}

	@Override
	void draw() {
		System.out.println("Rectangle::draw()");
	}
}

  创建实体类,继承抽象类,并实现其抽象方法。

/**
 * 圆形
 */
public class Circle extends Shape {

	public Circle() {
		super("This is a Circle.");
	}

	@Override
	void draw() {
		System.out.println("Circle::draw()");
	}
}

(3)模拟原型模式

  模拟从数据库中加载数据并缓存,当需要获取类的实例时,返回clone的实例。

/**
 * 创建类,模拟从数据库获取实体类数据,并缓存
 */
public class ShapeCache {

	private static Hashtable<Integer, Shape> shapeMap = new Hashtable<Integer, Shape>();

	public static Shape getShape(Integer id) {
		Shape cachedShape = shapeMap.get(id);
		return (Shape) cachedShape.clone();
	}

	public static Shape getShapeOri(Integer id) {
		Shape cachedShape = shapeMap.get(id);
		return (Shape) cachedShape;
	}

	/**
	 * 模拟对数据库的查询,创建类的实例
	 */
	public static void loadCache() {
		Circle circle = new Circle();
		circle.setId(1);
		shapeMap.put(circle.getId(), circle);

		Rectangle rectangle = new Rectangle();
		rectangle.setId(2);
		shapeMap.put(rectangle.getId(), rectangle);
	}
}

(4)测试原型模式实现

  测试实现

public class Test {

	public static void main(String[] args) {
		// 初始化加载实例对象
		ShapeCache.loadCache();

		// 获取实例1
		Shape shape1 = ShapeCache.getShape(1);
		System.out.println(shape1.getType());
		// clone实例比较
		System.out.println(ShapeCache.getShape(1) == ShapeCache.getShape(1));
		// 原始实例比较
		System.out.println(ShapeCache.getShapeOri(1) == ShapeCache.getShapeOri(1));
		System.out.println();

		// 获取实例2
		Shape shape2 = ShapeCache.getShape(2);
		System.out.println(shape2.getType());
		// clone实例比较
		System.out.println(ShapeCache.getShape(2) == ShapeCache.getShape(2));
		// 原始实例比较
		System.out.println(ShapeCache.getShapeOri(2) == ShapeCache.getShapeOri(2));
	}
}

  测试输出内容

This is a Circle.
false
true

This is a Rectangle.
false
true

三、相关内容

  • 注意事项
      与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现Cloneable,重写,深拷贝是通过实现Serializable读取二进制流。

  • 优缺点
    1、性能提高。
    2、逃避构造函数的约束。
    3、必须实现Cloneable接口。

  • 模式结构
    1、抽象原型类:规定了具体原型对象必须实现的接口。
    2、具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象。
    3、访问类:使用具体原型类中的clone()方法来复制新的对象。

  • 参考文章
    1、http://c.biancheng.net/view/1343.html
    2、https://www.runoob.com/design-pattern/prototype-pattern.html


更新时间:2020-08-12 14:26:31

本文由 新逸Cary 创作,如果您觉得本文不错,请随意赞赏
采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
原文链接:https://blog.xinac.cn/archives/java-design-prototype.html
最后更新:2020-08-12 14:26:31

评论

Your browser is out of date!

Update your browser to view this website correctly. Update my browser now

×