术语
prototype:原型
clone:克隆
案例
需求:将一只名字为杰克、性别为母的绵羊克隆10份;
要求每只绵羊的属性、性别都一致;
使用前
package com.javaxl.design.prototype.before;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:45
*/
public class Sheep {
private String name;
private String sex;
public Sheep(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
package com.javaxl.design.prototype.before;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:46
*
* 将一只名字为杰克、性别为母的绵羊克隆10份;
* • 要求每只绵羊的属性、性别都一致;
*
* 弊端:无法将当前的状态进行复制
*/
public class Client {
public static void main(String[] args) {
Sheep sheep1 = new Sheep("杰西", "母");
Sheep sheep2 = new Sheep("杰西", "母");
Sheep sheep3 = new Sheep("杰西", "母");
Sheep sheep4 = new Sheep("杰西", "母");
Sheep sheep5 = new Sheep("杰西", "母");
Sheep sheep6 = new Sheep("杰西", "母");
Sheep sheep7 = new Sheep("杰西", "母");
Sheep sheep8 = new Sheep("杰西", "母");
Sheep sheep9 = new Sheep("杰西", "母");
Sheep sheep10 = new Sheep("杰西", "母");
// 此时我要一只名为杰瑞的绵羊,其它绵羊属性与杰西一致;
// 那么按照这种设计,只能这么创建所需的绵羊
// 这种方式创建,目前只有两个属性问题不大,如果绵羊类有十几二十甚至更多的属性,那么是非常不方便的
Sheep sheep11 = new Sheep("杰瑞", "母");
}
}
使用后
package com.javaxl.design.prototype.after;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:45
*
* 使用原型设计模式进行设计
*/
public class Sheep implements Cloneable{
private String name;
private String sex;
public Sheep(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
System.out.println("被克隆了...");
return obj;
}
}
package com.javaxl.design.prototype.after;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:46
*
* 将一只名字为杰克、性别为母的绵羊克隆10份;
* • 要求每只绵羊的属性、性别都一致;
*
* 使用原型设计模式进行设计后的测试
*/
public class Client {
public static void main(String[] args) throws Exception{
Sheep sheep1 = new Sheep("杰西", "母");
Sheep sheep2 = (Sheep) sheep1.clone();
Sheep sheep3 = (Sheep) sheep1.clone();
Sheep sheep4 = (Sheep) sheep1.clone();
Sheep sheep5 = (Sheep) sheep1.clone();
Sheep sheep6 = (Sheep) sheep1.clone();
Sheep sheep7 = (Sheep) sheep1.clone();
Sheep sheep8 = (Sheep) sheep1.clone();
Sheep sheep9 = (Sheep) sheep1.clone();
Sheep sheep10 = (Sheep) sheep1.clone();
System.out.println(sheep1);
System.out.println(sheep2);
// 此时我要一只名为杰瑞的绵羊,其它绵羊属性与杰西一致;
// 按照原型设计模式,调用方Client类无需查找杰西相同部分的属性,只需变动差异部分属性进行克隆即可;
// 这种设计,目前只有两个属性使用起来感觉没多大区别,如果绵羊类有十几二十甚至更多的属性,那么感觉非常明显
sheep1.setName("杰瑞");//其它的属性不需要去关注
Sheep sheep11 = (Sheep) sheep1.clone();
System.out.println(sheep11);
}
}
结论:从对象创建的角度上来说,原型模式设计让相似的类实例创建更加的便捷
深层次的使用
浅拷贝
package com.javaxl.design.prototype.light;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:45
*
* 使用原型设计模式进行设计
*/
public class Sheep implements Cloneable{
private String name;
private String sex;
private Sheep friend;
public Sheep(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Sheep getFriend() {
return friend;
}
public void setFriend(Sheep friend) {
this.friend = friend;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", friend=" + friend +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
System.out.println("被克隆了...");
return obj;
}
}
浅拷贝特点:对象中实例变量,如果是引用变量,不会重新开辟空间
深拷贝
方式一
package com.javaxl.design.prototype.deep.one;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:45
* <p>
* 使用原型设计模式进行设计
*/
public class Sheep implements Cloneable {
private String name;
private String sex;
private Sheep friend;
private Sheep boyFriend;
public Sheep(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Sheep getFriend() {
return friend;
}
public void setFriend(Sheep friend) {
this.friend = friend;
}
public Sheep getBoyFriend() {
return boyFriend;
}
public void setBoyFriend(Sheep boyFriend) {
this.boyFriend = boyFriend;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", friend=" + friend +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
if (obj == null) {
return obj;
} else {
// 被克隆出来的绵羊(目前这只绵羊的朋友还是本体的朋友)
Sheep sheep = (Sheep) obj;
// 将本体的朋友也克隆一份出来,给克隆羊
Sheep friend = this.getFriend();
if (friend !=null){
sheep.setFriend((Sheep) friend.clone());
}
return sheep;
}
}
}
package com.javaxl.design.prototype.deep.one;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:46
* <p>
* 将一只名字为杰克、性别为母的绵羊克隆10份;
* • 要求每只绵羊的属性、性别都一致;
* <p>
* 使用原型设计模式进行设计后的测试
*/
public class Client {
public static void main(String[] args) throws Exception {
Sheep sheep1 = new Sheep("杰西", "母");
Sheep friend_jiexi = new Sheep("杰西的朋友", "公");
Sheep boyFriend_jiexi = new Sheep("杰西的男朋友", "公");
sheep1.setFriend(friend_jiexi);
sheep1.setBoyFriend(boyFriend_jiexi);
Sheep sheep2 = (Sheep) sheep1.clone();
System.out.println("第1只叫杰西的绵羊的朋友:" + sheep1.getFriend().hashCode());
System.out.println("第2只叫杰西的绵羊的朋友:" + sheep2.getFriend().hashCode());
System.out.println("第1只叫杰西的绵羊的男朋友:" + sheep1.getBoyFriend().hashCode());
System.out.println("第2只叫杰西的绵羊的男朋友:" + sheep2.getBoyFriend().hashCode());
}
}
方式二
package com.javaxl.design.prototype.deep.two;
import java.io.*;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:45
*
* 使用原型设计模式进行设计
*/
public class Sheep implements Cloneable,Serializable{
private String name;
private String sex;
private Sheep friend;
private Sheep boyFriend;
public Sheep getBoyFriend() {
return boyFriend;
}
public void setBoyFriend(Sheep boyFriend) {
this.boyFriend = boyFriend;
}
public Sheep(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Sheep getFriend() {
return friend;
}
public void setFriend(Sheep friend) {
this.friend = friend;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", friend=" + friend +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
System.out.println("被克隆了...");
return obj;
}
protected Object deepClone() throws CloneNotSupportedException, IOException, ClassNotFoundException {
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// 获取对象输出流
ObjectOutputStream oos = new ObjectOutputStream(bos);
// 将当前的对象
oos.writeObject(this);
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
Object obj = ois.readObject();
return obj;
}
}
public class Client {
public static void main(String[] args) throws Exception {
Sheep sheep1 = new Sheep("杰西", "母");
Sheep friend_jiexi = new Sheep("杰西的朋友", "公");
Sheep boyFriend_jiexi = new Sheep("杰西的男朋友", "公");
sheep1.setFriend(friend_jiexi);
sheep1.setBoyFriend(boyFriend_jiexi);
Sheep sheep2 = (Sheep) sheep1.deepClone();
System.out.println("第1只叫杰西的绵羊的朋友:" + sheep1.getFriend().hashCode());
System.out.println("第2只叫杰西的绵羊的朋友:" + sheep2.getFriend().hashCode());
System.out.println("第1只叫杰西的绵羊的男朋友:" + sheep1.getBoyFriend().hashCode());
System.out.println("第2只叫杰西的绵羊的男朋友:" + sheep2.getBoyFriend().hashCode());
}
}
注意事项和细节
创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率
不用重新初始化对象,而是动态地获得对象运行时的状态
如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码
缺点: 1、需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了 ocp 原则 2、实现深克隆的时候可能需要比较复杂的代码
over......
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有