java设计模式(7):原型模式

1. 什么是原型模式

        原型模式是一个创建型的模式,它实现了一个原型接口,这个接口用于创建当前对象的克隆。当直接创建对象的代价很大时,很适合采用这种方式。

        在执行Object类的clone()方法时,此类必须要实现Cloneable接口,这个接口没有任何方法。

public interface Cloneable {
}

        它只是告诉jvm,这个类可以执行clone()方法

        如果没有实现这个接口,则会提示CloneNotSupportedException.

2. 适用场景

        原型模式是利用对象克隆来实现的。使用克隆能节约大量的资源。利用克隆技术,可以拷贝对象的复制,而不影响原对象。

  •         a.通过new生成一个对象需要繁琐的数据准备或权限时
  •         b.一个对象需要在高代价的数据库操作后才能被创建时,可以缓存这个对象,在下一个请求时,返回它的克隆,在需要的时候更新数据库,以减少数据库的调用。
  •         c.一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。

3. 浅克隆与深克隆

        浅克隆

        java默认对基本数据类型进行值的克隆,对数组,集合,对象的引用等都还是引用的之前的地址。被复制的所有变量都含有和原来对象相同的值,只是复制对象,而不复制,它所引用的对象。

        深克隆

        需要手动的进行克隆代码的编写。把要复制的所引用的对象都复制了一遍。

4. 示例demo

        用户类(浅克隆)

public class User implements Cloneable{
	
	private String name;
	
	private String age;
	
	private String sex;
	
	private String[] array;
	
	private Role role;
	
	public User(Role role){
		this.role = role;
	}
	
	public User(){

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}

	public String[] getArray() {
		return array;
	}

	public void setArray(String[] array) {
		this.array = array;
	}

	@Override
	protected User clone() throws CloneNotSupportedException {
		// 浅克隆
		User temp = (User) super.clone();
		
		return temp;
		
	}
}

        角色类

public class Role implements Cloneable{
	
	private String roleName = "默认角色";
	
	private String memo = "默认备注";
	
	private String auth = "默认权限";

	public String getRoleName() {
		return roleName;
	}

	public void setRoleName(String roleName) {
		this.roleName = roleName;
	}

	public String getMemo() {
		return memo;
	}

	public void setMemo(String memo) {
		this.memo = memo;
	}

	public String getAuth() {
		return auth;
	}

	public void setAuth(String auth) {
		this.auth = auth;
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

        测试类

	public static void main(String[] args) throws CloneNotSupportedException {
		User user = new User(new Role());
		user.setArray(new String[]{"1"});
		
		User cloneUser = user.clone();
		
		System.out.println(user.getName() == cloneUser.getName());
		System.out.println(user.getRole() == cloneUser.getRole());
		System.out.println(user.getArray() == cloneUser.getArray());
	}

        浅克隆时运行结果

true
true
true

        深克隆,修改用户类中的clone()方法

	@Override
	protected User clone() throws CloneNotSupportedException {
		// 深克隆
		User temp = (User) super.clone();
		
		temp.role = (Role) this.role.clone();
		
		temp.array = this.array.clone();
		
		return temp;
		
	}

        深克隆时的运行结果:

true
false
false

注意到这里的role和array 在深克隆前后,在==时返回false,说明引用的不是同一个对象。

5. 总结

        原型模式优点:

        a.对象是通过clone方法生成,不是通过new 生成,节省了资源,提高了效率。

        b.在多线程环境下,需要生成同一个类的多个对象的时候,不会产生并发等问题。

        c.逃避构造函数的约束,直接在内存中拷贝,不会执行构造方法。

        原型模式缺点:

        a.每个原型都要实现Cloneable接口,复写clone()方法

        b.如果是对之前的代码进行改造,则会是一种侵入式改造,违背了“开闭”原则

猜你喜欢

转载自blog.csdn.net/u014209205/article/details/80671588