android框架之基础 原型设计模式

原型设计模式也是创建型几个模式之一,提到创建型模式工厂模式,都以为是new一个对象出来,但是原型设计模式,并不通过new创建对象
定义:
原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例
用途:
原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据
原型模式就是把一个对象中的属性的值赋值给另外一个对象属性的值

使用复制也就是克隆必须要实现Cloneable接口,

public interface Cloneable {} 发现这又是一个标记接口,还有就是要重写Object类中的clone()方法
package com.prototype;
public class Student implements Cloneable {
	private String name;
	private int age;
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();
		return obj;
	}
}
测试:
package com.prototype;
public class Test {
	public static void main(String[] args) throws CloneNotSupportedException {
		Student stu = new Student("zhouguizhi", 18);
		System.out.println("stu="+stu);
		Student cloneStu = (Student) stu.clone();
		System.out.println("cloneStu="+cloneStu);
		System.out.println("name="+cloneStu.getName()+"--"+"age="+cloneStu.getAge());
	}
}
运行结果:
stu=com.prototype.Student@2a139a55
cloneStu=com.prototype.Student@15db9742
name=zhouguizhi--age=18
你会发现克隆出来的对象内存地址值和原来的对象是不同的,所以这二个不是同一个对象,但是值是相同的,创建对象时属性的值都是默认值,而克隆出来的对象中的值是原始对象的属性值,

android框架之基础 原型设计模式_第1张图片

其实克隆就是类似这种把一个对象中的值赋值给另外一个对象,比如这样子:

Student stu = new Student("zhouguizhi", 18);
		System.out.println("stu="+stu);
		Student cloneStu = new Student();
		cloneStu.setName(stu.getName());
		cloneStu.setAge(stu.getAge());
这是这种效率比较低而已,所以java会把克隆也就是clone()方法放在native层,用c处理起来效率更高.

现在Student类上添加一个朋友的属性对象

package com.prototype;
public class Student implements Cloneable {
	private String name;
	private int age;
	private Friend friend;
	
	public Student(String name, int age, Friend friend) {
		super();
		this.name = name;
		this.age = age;
		this.friend = friend;
	}
	public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();
		return obj;
	}
	public Friend getFriend() {
		return friend;
	}
	public void setFriend(Friend friend) {
		this.friend = friend;
	}
	class Friend{
		private int age;
		private String name;
		public Friend(int age, String name) {
			this.age = age;
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
	}
}
Test.java
package com.prototype;
import com.prototype.Student.Friend;
public class Test {
	public static void main(String[] args) throws CloneNotSupportedException {
		Friend friend  =new Student().new Friend(20,"xiaofang");
		System.out.println("friend="+friend);
		Student stu = new Student("zhouguizhi", 18,friend);
		Student cloneStu = (Student) stu.clone();
		Friend cloneFriend  = cloneStu.getFriend();
		System.out.println("克隆后的friend="+friend);
		cloneFriend.setAge(99);//改变Friend对象中的值
		//获取原数据fried对象中的age值
		System.out.println("age="+friend.getAge());
	}
}
运行结果:

friend=com.prototype.Student$Friend@2a139a55克隆后的friend=com.prototype.Student$Friend@2a139a55age=99

从打印的结果看,明明是在克隆后的Student对象上获取到Friend对象后改变了age的值,但是原来的值也跟着改变了,说明了这个Friend对象在内存中是共享同一个对象才会造成这样结果
浅克隆:对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象
从上面的问题就引出了深克隆的问题
深克隆:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制(会创建对象在内存中分配就不一样)

对于上面的问题用深克隆可以解决

再次看下Student类的代码:

package com.prototype;
public class Student implements Cloneable {
	private String name;
	private int age;
	private Friend friend;
	
	public Student(String name, int age, Friend friend) {
		super();
		this.name = name;
		this.age = age;
		this.friend = friend;
	}
	public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();
		Student student = (Student) obj;
		student.friend = (Friend) this.friend.clone();//把属性也进行克隆
		return obj;
	}
	public Friend getFriend() {
		return friend;
	}
	public void setFriend(Friend friend) {
		this.friend = friend;
	}
	class Friend implements Cloneable {
		private int age;
		private String name;
		public Friend(int age, String name) {
			this.age = age;
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		@Override
		protected Object clone() throws CloneNotSupportedException {
			Object obj = super.clone();
			return obj;
		}
	}
}
Test.java
package com.prototype;
public class Test {
	public static void main(String[] args) throws CloneNotSupportedException {
		Friend friend  =new Friend(20,"xiaofang");
		System.out.println("friend="+friend);
		Student stu = new Student("zhouguizhi", 18,friend);
		Student cloneStu = (Student) stu.clone();
		Friend cloneFriend  = cloneStu.getFriend();
		System.out.println("克隆后的friend="+cloneFriend);
		cloneFriend.setAge(99);//改变Friend对象中的值
		//获取原数据fried对象中的age值
		System.out.println(friend==cloneFriend);
		System.out.println("age="+friend.getAge());
	}
}
运行结果:

friend=com.prototype.Friend@2a139a55
克隆后的friend=com.prototype.Friend@15db9742falseage=20

从结果上看发现friend和克隆出来的cloneFriend对象不是同一个对象了,而且改变克隆后的值也不会影响之前的值了.
从深克隆中发现也用到了浅克隆,上面的Friend对象重写了clone()方法就是浅克隆了,说明克隆可以多层嵌套.
其实使用序列化和反序列化也可以实现深克隆

package com.prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Student implements Cloneable,Serializable {
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private Friend friend;
	public Student(String name, int age, Friend friend) {
		super();
		this.name = name;
		this.age = age;
		this.friend = friend;
	}
	public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Friend getFriend() {
		return friend;
	}
	public void setFriend(Friend friend) {
		this.friend = friend;
	}
	/**
	 * 序列化和反序列化实现深克隆
	 */
	public Object deepClone() throws Exception {
         //将对象写到流里
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(bos);
         oos.writeObject(this);
         //从流里读回来
         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
         ObjectInputStream ois = new ObjectInputStream(bis);
         return ois.readObject();
	}
}
Test.java
package com.prototype;
public class Test {
	public static void main(String[] args) throws Exception {
		Friend friend  =new Friend(20,"xiaofang");
		System.out.println("friend="+friend);
		Student stu = new Student("zhouguizhi", 18,friend);
		Student student = (Student)stu.deepClone();
		Friend cloneFriend  = student.getFriend();
		System.out.println("克隆后的cloneFriend="+cloneFriend);
		cloneFriend.setAge(18);//原来是20 改为18
		System.out.println("原friend中的age值="+friend.getAge());
	}
}
运行结果:

friend=com.prototype.Friend@2a139a55
克隆后的cloneFriend=com.prototype.Friend@4554617c
原friend中的age值=20

你可能感兴趣的:(架构之路)