设计模式之原型模式

  原型模式与构造器模式、单例模式、工厂方法模式、抽象工厂模式一样,都属于创建型模式。它用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。当需要创建多个实例,而new一个对象需要非常繁琐的数据准备和访问权限时,用原型模式就再合适不过了。原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件:

1、实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。

2、重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。

 

  原型模式很简单,一个实现了Cloneable接口的类基本就是核心了,来个例子:

class Message implements Cloneable {
	private String header;
	private String content;

	public String getHeader() {
		return header;
	}

	public void setHeader(String header) {
		this.header = header;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public Message clone() throws CloneNotSupportedException {
		Message message = (Message) super.clone();
		return message;
	}
}

  这是一个Message类,它有两个字段以及对应的get、set方法,这只是个例子,事实上只有两个字段的情况下new起来还是很容易的,但是如果有十来个,那就挺麻烦的了。用原型模式只需要在第一个new出来的对象上调用Clone()方法就好了

public static void main(String[] args) {
		Message msg = new Message();
		msg.setHeader("Bank Of China!");
		msg.setContent("中国银行开业大酬宾。。。");
		try {
			Message msgCopy = msg.clone();
			msgCopy.setHeader("Bank Of America");
			
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}

  这样就可以很容易地制造出许多副本,修改他们不同的地方之后,就可以独自使用了。需要注意的是,java里提供的Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。我们可以测试一下:

public static void main(String[] args) {
		Message msg = new Message();
		msg.setHeader("Bank Of China!");
		msg.setContent("中国银行开业大酬宾。。。");
		try {
			Message msgCopy = msg.clone();
			msgCopy.setHeader("Bank Of America");
			System.out.println(msg.getHeader()==msgCopy.getHeader());
			System.out.println(msg.getContent()==msgCopy.getContent());
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}

  运行可以看到打印出来的是false和true。要实现里面的引用对象深拷贝怎么办,对于自身具有clone方法的引用对象,再调用一下其clone方法就OK了,对于没有的,最简单的用字节流读写一下就好了。

posted @ 2017-12-28 14:22  fengshenjingjun  阅读(162)  评论(0编辑  收藏  举报