我写拷贝模式(prototype原型模式)
你拷贝或不拷贝,她一直在哪里,风力不走,雨里不去,你忍心留她一个人?哦可惜爱不是几滴眼泪几封情书哦— 这样的话或许有点残酷 等待着别人给幸福的人 往往过的都不怎么幸福!咔咔咔以上和拷贝(prototype原型模式)有半毛钱的关系吗?我这不是借物喻人,寓情于景吗,请原谅我的语文天赋点的有点歪……^_^~
开局一声吼,代码全靠编
哎客官不可以,洒家风华正茂,一时意气用事,当不得真,您容我重新组织一下语言。客官留步啊,您请~听~我~说~
听说白雪公主在逃跑,小红帽在担心大灰狼,啊我这嗓子一如既往的阔以,肿么办,辣么强,还要啥自行车。
坚决不跑题了哈,编起来go
话说天下大事,不对不对咳咳,话说有个People类俗称javaBean,长这吊样
public class People {
private String name;
private int 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;
}
}
长这吊样的多了去了,有啥用?
这不是要说到拷贝模式(prototype原始模型)吗,咱改一改给他来点料,实现一个标识接口Cloneable后变成这货了
public class People implements Cloneable{
private String name;
private int age;
public People(String name, int age) {
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 {
return super.clone();
}
}
如果不实现Cloneable,上面的clone方法是会报错的呀,当然了能报错就能解决,换成下方代码一次就好,我陪你天涯海角,oh不~
@Override
protected Object clone() throws CloneNotSupportedException {
People people = new People(name,age);
return (People)people;
}
PS一定要实现Cloneable不要问问什么,因为我不会告诉你这就是原型模式的核心哼(づ。◕‿‿◕。)づ
实现完了咱就测试一下代码的流畅度,测试代码如下:
public static void main(String[] args) {
People people = new People("kevin",25);
System.out.println("people:"+people.toString());
try {
Object clone = people.clone();
if (clone instanceof People){
People people1 = (People) clone;
System.out.println("people1:"+people1.toString());
System.out.println("people==people1: " + (people==people1));
System.out.println("name: "+people.getName().equals(people1.getName()));
System.out.println("age==age1: "+(people.getAge() == people1.getAge()));
}
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
运行结果
people:name=kevin,age=25
people1:name=kevin,age=25
people==people1: false
name: true
age==age1: true
拷贝完以后数据是一样的说明是对的,但是巧的是name居然相等,age也居然相等,那不就是说引用的对象的地址是同一块地址呀,通俗的说,只是给这个people换了身行头因为(people==people1: false)看出来滴,内饰丝毫不改动呀,可能这样看的不清楚,咱给他加点work瞧一瞧
新People如下:
public class People implements Cloneable {
private String name;
private int age;
private Work work;
public People(String name, int age) {
this.name = name;
this.age = age;
this.work = new Work("it码农", 9527);
}
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 Work getWork() {
return work;
}
public void setWork(Work work) {
this.work = work;
}
@Override
public String toString() {
return "name=" + name + ",age=" + age;
}
class Work {
private String workName;
private int workNo;
public Work(String workName, int workNo) {
this.workName = workName;
this.workNo = workNo;
}
public String getWorkName() {
return workName;
}
public void setWorkName(String workName) {
this.workName = workName;
}
public int getWorkNo() {
return workNo;
}
public void setWorkNo(int workNo) {
this.workNo = workNo;
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
再来个测试代码看看
public static void main(String[] args) {
People people = new People("kevin",25);
System.out.println("people:"+people.toString());
try {
Object clone = people.clone();
if (clone instanceof People){
People people1 = (People) clone;
System.out.println("people1:"+people1.toString());
System.out.println("people==people1: " + (people==people1));
System.out.println("name: "+people.getName().equals(people1.getName()));
System.out.println("age==age1: "+(people.getAge() == people1.getAge()));
System.out.println("work: "+(people.getWork() == people1.getWork()));
People.Work work = people.getWork();
People.Work work1 = people1.getWork();
work.setWorkName("i am work...");
System.out.println(work.getWorkName());
System.out.println(work1.getWorkName());
}
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
测试结果如下:
people:name=kevin,age=25
people1:name=kevin,age=25
people==people1: false
name: true
age==age1: true
work: true
i am work...
i am work...
注意(work: true)这次很直观的发现引入的work是相等的,也就是拷贝的people依旧持有被拷贝people的work,通过给work(people中的work)赋值(i am work…),work1(拷贝完后的对象people1中的work)也跟着改变了内容,也就是说我只是做了上层拷贝(浅拷贝)只是神似罢了,哇那我不就可以引出深入一点的问题(深拷贝)了吗,机智如我呀,不如去吃个鸡?咳咳跑题了哈,往下走走
深拷贝的People长如下这吊样,关键点是需要实现Serializable接口 ,People、Work必须要实现。因为我们要通过串行化来做深拷贝(deepClone方法),clone()方法咱做了浅拷贝,注Cloneable不能丢呀
public class People implements Cloneable,Serializable {
private String name;
private int age;
private Work work;
public People(String name, int age) {
this.name = name;
this.age = age;
this.work = new Work("it码农", 9527);
}
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 Work getWork() {
return work;
}
public void setWork(Work work) {
this.work = work;
}
@Override
public String toString() {
return "name=" + name + ",age=" + age;
}
class Work implements Serializable{
private String workName;
private int workNo;
public Work(String workName, int workNo) {
this.workName = workName;
this.workNo = workNo;
}
public String getWorkName() {
return workName;
}
public void setWorkName(String workName) {
this.workName = workName;
}
public int getWorkNo() {
return workNo;
}
public void setWorkNo(int workNo) {
this.workNo = workNo;
}
}
/**
* 浅拷贝
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* 深拷贝
* @return
*/
public Object deepClone() {
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(this);
bais = new ByteArrayInputStream(baos.toByteArray());
ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
close(baos);
close(oos);
close(bais);
close(ois);
}
return null;
}
/**
* 关闭流
* @param closeable
*/
private static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
测试代码走一走:
public static void main(String[] args) {
People people = new People("kevin", 25);
System.out.println("people:" + people.toString());
Object clone = people.deepClone();
if (clone instanceof People) {
People people1 = (People) clone;
System.out.println("people1:" + people1.toString());
System.out.println("people==people1: " + (people == people1));
System.out.println("name: " + people.getName().equals(people1.getName()));
System.out.println("age==age1: " + (people.getAge() == people1.getAge()));
System.out.println("work: " + (people.getWork() == people1.getWork()));
People.Work work = people.getWork();
People.Work work1 = people1.getWork();
work.setWorkName("i am work...");
System.out.println(work.getWorkName());
System.out.println(work1.getWorkName());
}
}
输出结果:
people:name=kevin,age=25
people1:name=kevin,age=25
people==people1: false
name: true
age==age1: true
work: false
i am work...
it码农
老铁们,(work: false)work不相等了,深拷贝成功了呀,修改work的workName不会再影响work1的workName啦,激动呀。
咦~这里的串行化不就是序列化和反序列化吗,老铁还不是信手拈来一段序列化代码
请看,序列化little toolKit:这可是我做redis缓存数据用的序列化呀,倾囊相授,不要迷恋我哦
public class SerializeUtil {
/**
* 单一对象序列化
* @param object
* @return
*/
public static byte[] serialize(Object object) {
if (object == null) {
throw new IllegalArgumentException("object is null");
}
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
byte[] bytes = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
bytes = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(oos);
close(baos);
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
private static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 单一对象反序列化
* @param bytes
* @return
*/
public static Object unserialize(byte[] bytes) {
if (bytes == null) {
throw new IllegalArgumentException("bytes is null");
}
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
close(bais);
close(ois);
}
return null;
}
/**
* 列表数据的序列化
* @param list
* @return
*/
public static byte[] serializeList(List<?> list) {
if (list == null || list.size() == 0) {
return null;
}
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
byte[] bytes = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
for (Object o : list) {
oos.writeObject(o);
}
bytes = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(baos);
close(oos);
}
return null;
}
/**
* 列表数据的反序列化
* @param bytes
* @return
*/
public static List<?> unserializeList(byte[] bytes) {
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
List<Object> list = new ArrayList<>();
try {
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
while (bais.available() > 0){
Object object = ois.readObject();
if (object == null){
break;
}
list.add(object);
}
return list;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
close(bais);
close(ois);
}
return null;
}
}
一个明朗的天,心情随着音乐摇摆呀(◡ᴗ◡✿)