java设计模式之5—原型模式(Prototype模式) 结合生活代码理解

定义

Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。

特点

  • 由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。
  • 目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。
  • 根据对象克隆深度层次的不同,有浅度克隆与深度克隆

应用场景

  1. 资源优化场景。
  2. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  3. 性能和安全要求的场景。
  4. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  5. 一个对象多个修改者的场景。
  6. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
  7. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。

缺点

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

生活映射

相信熟悉java的朋友到这里已经了解原型模式了,在我们生活中有什么原型模式呢,其实编程来源于生活嘛,万物皆对象(多么牛的话),前段时间我看了一个电影,叫《我不是药神》,没有看过这部电影的朋友可以看一下(我在这里安利一波,很经典),其实在电影里面就有原型模式,瑞士的诺瓦医药公司投入巨大的资金、人力等开发出了一款能够抗击慢粒白血病的药物(这就是原型模式中的原型),而印度的一个制药公司只需要分析出药品中的材料,就可以轻松制造出相同功效的药物(原型模式中的克隆,较小的开销实现较大的效率),假药的制作(我指的是功效相同,但是医疗手册中没有的药)我认为就是生活中的原型模式。

实现代码

代码可在码云中下载(包名为e_prototype)
https://gitee.com/XiaoSa12138/java-models

浅度克隆(被克隆对象中只包含基本类型)

/**
 * 被克隆的bean继承Cloneable接口,可以使用Object的clone方法克隆
 */
public class Person implements Cloneable {

	private String name;
	private int age;
	private double height;
	private List<String> friends;

	//sets&gets

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", height=" + height + ", friends=" + friends + "]";
	}

	/**
	 * 克隆方法
	 */
	public Person getPerson() {
		try {
			return (Person) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}

}
/**
 * 测试类
 */
public class Main {

	public static void main(String[] args) {
		Person p1 = new Person();
		p1.setName("张三");
		p1.setAge(10);
		p1.setHeight(110.1);
		
		Person p2 = p1.getPerson();
		p2.setName("李四");
		
		System.out.println(p1);
		System.out.println(p2);
	}
}

深度克隆(被克隆对象中包含对象类型)

/**
 * 被克隆的bean继承Cloneable接口,可以使用Object的clone方法克隆
 */
public class Person implements Cloneable {

	private String name;
	private int age;
	private double height;
	private List<String> friends;

	//sets&gets

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", height=" + height + ", friends=" + friends + "]";
	}

	/**
	 * 克隆方法
	 * 由于对象中含有引用类型的属性,浅克隆不会克隆引用类型指向的对象,只会克隆对象的引用,此时原型对象与克隆对象的引用属性依然使用的同一个对象
	 * 因此,需要在克隆时将引用类型的属性再创建一遍,并复制数据,使与原型对象完全脱离,实现深度克隆
	 */
	public Person getPerson() {
		try {
			Person person = (Person) super.clone();
			List<String> friends = new ArrayList<>();
			for (String friend : this.friends) {
				friends.add(friend);
			}
			person.setFriends(friends);
			return person;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}

}

/**
 * 测试类
 */
public class Main {

	public static void main(String[] args) {
		Person p1 = new Person();
		p1.setName("张三");
		p1.setAge(10);
		p1.setHeight(110.1);
		
		List<String> friends = new ArrayList<>();
		friends.add("黛玉晴雯子");
		friends.add("木村躲债");
		p1.setFriends(friends);
		
		Person p2 = p1.getPerson();
		p2.setName("李四");
		
		System.out.println(p1);
		System.out.println(p2);
		
		friends.add("萧十一郎");
		
		System.out.println(p1);
		System.out.println(p2);
		
	}
	
}

猜你喜欢

转载自blog.csdn.net/weixin_42997554/article/details/86562764
今日推荐