设计模式学习JAVA(四)创建性模式——原型模式

参考链接:http://www.runoob.com/design-pattern/prototype-pattern.html

示例代码:https://github.com/jianghan0712/design-pattern

一、综述

        所谓原型模式,就是在在一个频繁创建同一个对象实体的系统中,因为频繁的构建相同的实体,很繁琐,所以通过原型的“自我复制”,来达到创建对象的目的。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

        在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用


二、主要思想

        用原型实例指定创建对象的种类,直接通过拷贝这些原型创建新的对象,而不是通过构造函数创建对象

        关键在于:1、实现克隆操作,浅拷贝实现 Cloneable重写,或深拷贝是通过实现 Serializable 读取二进制流。
                          2、原型模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些"易变类"拥                                  有稳定的接口。


三、示例UML

                            


四、示例代码

          我们通过以下场景进行模拟。假设有一个通用虚拟类Shape,有两个实体类Square和Rectangle,有一个ShapeCache作为原型的缓存类,以一个Map<id,Shape>来存储两个原型对象,当需要新创建对象时,直接从cache中复制原型出来。(浅拷贝)

统一虚拟类Shape.java

public abstract class Shape implements Cloneable{
	private String id;
	protected String type;
	
	abstract void draw();
	
	public Object clone() {
		Object clone = null;
	    try {
	        clone = super.clone();
	    } catch (CloneNotSupportedException e) {
	        e.printStackTrace();
	    }
	    return clone;
	}

	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;
	}	
}

两个实体类

Square.java

public class Square extends Shape{
	public Square() {
		type = "Square";
	}
	
	@Override
	public void draw() {
		// TODO Auto-generated method stub
		System.out.println("Square:dram()");
	}
}

Rectangle.java

public class Rectangle extends Shape{
	public Rectangle() {
		type = "Rectangle";
	}
	@Override
	public void draw() {
		// TODO Auto-generated method stub
		System.out.println("Rectangle:dram()");
	}
}

原型缓存及复制类ShapeCache.java

/*
 * 模拟从数据库获取实体类,并把他们存在一个cache(hashMap)中 
 */
public class ShapeCache {
	private static HashMap<String, Shape> shapeMap = new HashMap<String, Shape>();
	
	public static Shape getShape(String shapeId) {
		return (Shape)shapeMap.get(shapeId).clone();
	}

	//模拟从数据库中load2种数据类型,把他们存到map中,当需要新创建一个对应实体时,调用getShape来直接复制一个对象,而不是new
	public static void loadCache() {
		 Square square = new Square();
	     square.setId("Square");
	     shapeMap.put(square.getId(),square);
	 
	     Rectangle rectangle = new Rectangle();
	     rectangle.setId("Rectangle");
	     shapeMap.put(rectangle.getId(),rectangle);
	}
}

测试类Main.java

public class Main {
	public static void main(String[] args) {
	    ShapeCache.loadCache();
		 
	    Shape clonedShape = (Shape) ShapeCache.getShape("Square");
	    System.out.println("Shape : " + clonedShape.getType());        
	 
	    Shape clonedShape2 = (Shape) ShapeCache.getShape("Rectangle");
	    System.out.println("Shape : " + clonedShape2.getType());        
	}
}

五、总结

        适用场景:1、资源优化场景。 
                          2、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。 
                          3、性能和安全要求的场景。 
                          4、通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。 
                          5、一个对象多个修改者的场景。
                          6、一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多                                 个对象供调用者使用。 

         优点:1、性能提高。 2、逃避构造函数的约束。

         缺点:配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一                      个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值