简说设计模式——原型模式

一、什么是原型模式

       原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。UML结构图如下:


       其中,Prototype为原型类,声明一个克隆自身的接口;ConcretePrototype为具体实现类,实现一个克隆自身的操作;而客户端Client只需让一个原型克隆自身,从而创建一个新的对象。

    1. Prototype

public abstract class Prototype implements Cloneable {
	
	private String id;
	
	public Prototype(String id) {
		this.id = id;
	}
	
	public String getId() {
		return id;
	}

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

    2. ConcretePrototype

       创建当前对象的浅表副本。

public class ConcretePrototype extends Prototype {

	public ConcretePrototype(String id) {
		super(id);
	}
	
}

    3. Client

public class Client {

	public static void main(String[] args) {
		ConcretePrototype p1 = new ConcretePrototype("Hello");
		ConcretePrototype c1 = (ConcretePrototype) p1.clone();
		System.out.println(c1.getId());
	}
	
}

       运行结果为“Hello”,此时ConcretePrototype的对象p1得到了新的实例c1。

二、原型模式的应用

    1. 何时使用

  • 当一个系统应该独立于它的产品创建、构成和表示时。
  • 当要实例化的类是在运行时刻指定时(如动态装载)。
  • 为了避免创建一个与产品类层次平行的工厂类层次时。
  • 当一个类的实例只能有几种几个不同状态组合中的一种时。

    2. 优点

  • 性能优良。不用重新初始化对象,而是动态地获取对象运行时的状态。
  • 逃避构造函数的约束。

    3. 缺点

  • 配置克隆方法需要对类的功能进行通盘考虑。
  • 必须实现Cloneable接口。

    4. 使用场景

  • 资源优化场景。
  • 性能和安全要求的场景。
  • 一个对象多个修改者的场景。
  • 一般与工厂方法模式一起出现,通过clone方法创建一个对象,然后由工厂方法提供给调用者。

    5. 应用实例

  • 细胞分裂
  • Java中的Object.clone()方法
  • 复印

三、原型模式的实现

       下面我们创建一个抽象类和扩展了它的实体类,即图形类与圆形、矩形、三角形。之后再通过一个cache类将对象存储在一个Hashtable中,并在请求的时候返回它们的克隆。UML图如下:


    1. Shape类

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

public abstract class Shape implements Cloneable {
	
	private String id;
	protected String type;
	
	public abstract void draw();

	public String getId() {
		return id;
	}

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

	public String getType() {
		return type;
	}
	
	@Override
	public Shape clone() {
		Shape prototype = null;
		
		try {
			prototype = (Shape) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		
		return prototype;
	}
	
}

    2. 实现类

       创建扩展了上面抽象类的实现类,这里以Circle为例。

public class Circle extends Shape {

	public Circle() {
		type = "圆形";
	}
	
	@Override
	public void draw() {
		System.out.println("圆形类的draw方法");
	}

}

    3. ShapeCache

       获取实体类,并存于Hashtable中。

public class ShapeCache {

	private static Hashtable<String, Shape> shapeMap = new Hashtable<>();
	
	public static Shape getShape(String shapeId) {
		Shape shape = shapeMap.get(shapeId);
		
		return shape.clone();
	}
	
	//添加三种图形
	public static void loadCache() {
		Circle circle = new Circle();
		circle.setId("1");
		shapeMap.put(circle.getId(), circle);
		
		Triangle triangle = new Triangle();
		triangle.setId("2");
		shapeMap.put(triangle.getId(), triangle);
		
		Rectangle rectangle = new Rectangle();
		rectangle.setId("3");
		shapeMap.put(rectangle.getId(), rectangle);
	}
	
}

    4. Client客户端

public class Client {

	public static void main(String[] args) {
		ShapeCache.loadCache();
		
		Shape clonedShape = ShapeCache.getShape("1");
		System.out.println("图形:" + clonedShape.getType());
		
		Shape clonedShape2 = ShapeCache.getShape("2");
		System.out.println("图形:" + clonedShape2.getType());
		
		Shape clonedShape3 = ShapeCache.getShape("3");
		System.out.println("图形:" + clonedShape3.getType());
		
	}
	
}

       运行结果如下:



       源码地址:https://gitee.com/adamjiangwh/GoF

猜你喜欢

转载自blog.csdn.net/adamjwh/article/details/80168278
今日推荐