设计模式系列--原型模式

定义

原型模式是指 通过原型实例指定创建对象的类型,克隆该实例属性相同的新对象。调用者不需要知道任何创建细节,不调用构造函数。因此原型模式也被称为克隆模式。

适用场景:

1、类初始化消耗资源较多

2、new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)

3、构造函数比较复杂

原型模式创建方式分为两种:浅克隆 ,深克隆

实现方式

1、浅克隆

克隆出的新对象的引用属性内存地址还是指向原实例属性地址。即新对象与原对象引用属性共用同一内存地址,新的对象随着原实例引用属性变化而变化

Cat 接口 ,定义 clone 方法

public interface Animal {

	Animal clone();
}

Cat 实现类

import java.util.List;

public class Cat implements Animal {

	private Integer age;

	private String name;

	private List ability;

	public Integer getAge() {
		return age;
	}

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

	public String getName() {
		return name;
	}

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

	public List getAbility() {
		return ability;
	}

	public void setAbility(List ability) {
		this.ability = ability;
	}

	@Override
	public String toString() {
		return "Cat{" +
				"age=" + age +
				", name='" + name + '\'' +
				", ability=" + ability +
				'}';
	}

	@Override
	public Animal clone() {
		Cat cat = new Cat();
		cat.setAge(this.age);
		cat.setName(this.name);
		cat.setAbility(this.ability);
		return cat;
	}
}

模拟客户端 使用原型模式

public class Client {

	public Animal startClone(Animal animal) {
		return animal.clone();
	}

}

Test 测试类

public class Test {

	public static void main(String[] args) {
		Cat cat = new Cat();
		List ability = new ArrayList<>();
		ability.add("抓老鼠");
		ability.add("抓鱼");
		cat.setAge(1);
		cat.setName("ketty");
		cat.setAbility(ability);

		Client client = new Client();
		Cat catClone = (Cat) client.startClone(cat);

		System.out.println(cat);
		ability.add("打架");
		System.out.println(cat);
		System.out.println(catClone);

	}
}

设计模式系列--原型模式_第1张图片

可以发现 ,当引用变量 ability 变化时,浅克隆后的新对象 相应属性也随之变化。

2、深克隆

克隆过程中为新对象引用属性分配新的内存地址,不会随着原实例对象引用属性的变化而变化

Dog 实现 Animal 接口,并通过字节码 序列化操作

import java.io.*;
import java.util.List;

public class Dog implements Serializable, Animal {

	private Integer age;

	private String name;

	private List ability;

	public Integer getAge() {
		return age;
	}

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

	public String getName() {
		return name;
	}

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

	public List getAbility() {
		return ability;
	}

	public void setAbility(List ability) {
		this.ability = ability;
	}

	@Override
	public String toString() {
		return "Dog{" +
				"age=" + age +
				", name='" + name + '\'' +
				", ability=" + ability +
				'}';
	}


	@Override
	public Animal clone() {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(this);
			ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bis);
			Dog dog = (Dog)ois.readObject();
			return dog;
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
}

Test 测试类

public class Test {

	public static void main(String[] args) {
		Dog dog = new Dog();
		List ability = new ArrayList<>();
		ability.add("看家");
		dog.setName("嘟嘟");
		dog.setAge(2);
		dog.setAbility(ability);

		Client client = new Client();
		Dog dogClone = (Dog)client.startClone(dog);
		System.out.println(dog);
		ability.add("和主人玩耍");
		System.out.println(dog);
		System.out.println(dogClone);
	}
}

设计模式系列--原型模式_第2张图片

可以发现,当原型实例引用变量ability变化时,克隆后的新对象并不会随之变化

当然在Java中,我们可以直接 实现Cloneable 接口,重写clone 方法进行克隆操作

public class Pig implements Cloneable, Serializable {

	private Integer age;

	private String name;

	private List ability;

	public Integer getAge() {
		return age;
	}

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

	public String getName() {
		return name;
	}

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

	public List getAbility() {
		return ability;
	}

	public void setAbility(List ability) {
		this.ability = ability;
	}

	@Override
	public String toString() {
		return "Dog{" +
				"age=" + age +
				", name='" + name + '\'' +
				", ability=" + ability +
				'}';
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(this);
			ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bis);
			Dog dog = (Dog) ois.readObject();
			return dog;
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

}

你可能感兴趣的:(设计模式)