设计模式之原型模式
Posted lancelee98
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之原型模式相关的知识,希望对你有一定的参考价值。
原型模式——PrototypePattern
原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
用于复制对象。
原型模式结构:
原型类Prototype(原型类,声明克隆自身的接口)
具体原型类ConcretePrototype(具体的原型类,继承原型类,实现克隆自身的操作)
关于复制分为浅复制和深复制
浅复制:创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。因此,原始对象及其副本引用同一个对象。(引用类型会共享)
深复制:对于旧对象的字段是引用类型,新建一个新的同类型的引用对象,将旧字段的引用类型中的内容赋给新建的引用对象,再将新建的引用对象赋给复制的对象。(就是复制所有的东西,引用类型的会新建)
Java中实现克隆的方法:
- 1、新建原型类,声明克隆接口,在具体原型类中引用其接口,实现具体克隆操作
-
-
- 原型类
public interface IExprience { public Object Clone(); }
- 具体原型类
public class Experience implements IExprience{ private String educationBackground; private String skills; public void setExperience(String educationBackground,String skills) { this.educationBackground=educationBackground; this.skills=skills; }public Object Clone() { Experience experience=new Experience(); experience.setExperience(this.educationBackground,this.skills); return experience; } }
- 主函数
Experience experience=new Experience(); experience.setExperience("专科","C#"); Experience experience1=(Experience) experience.Clone(); System.out.println(experience); System.out.println(experience1);
- 原型类
-
-
- 2、不声明原型类,直接在具体类中实现clone操作
-
-
- 具体类
public class Experience{ private String educationBackground; private String skills; public void setExperience(String educationBackground,String skills) { this.educationBackground=educationBackground; this.skills=skills; } public Experience Clone() { Experience experience=new Experience(); experience.setExperience(this.educationBackground,this.skills); return experience; } }
- 具体类
-
-
- 3、具体类中继承Java的Cloneable接口 调用super.clone()方法
-
-
-
1 public class ExperienceDeepCopy implements Cloneable{//这里继承了Cloneable接口 2 private String educationBackground; 3 private String skills; 4 5 public void setExperience(String educationBackground,String skills) { 6 this.educationBackground=educationBackground; 7 this.skills=skills; 8 } 9 10 @Override 11 public String toString() { 12 return educationBackground+skills; 13 } 14 public ExperienceDeepCopy Clone() 15 { 16 try { 17 return (ExperienceDeepCopy) super.clone();//这里使用了Java提供的clone方法,这个clone方法是浅复制,需要放在try catch中 18 } 19 catch (Exception e) 20 { 21 e.printStackTrace(); 22 return null; 23 } 24 } 25 }
-
-
-
Java 中的super.clone():
我们知道该clone()方法是使用Object类的clone()方法,但是该方法存在一个缺陷,它并不会将对象的所有属性全部拷贝过来,而是有选择性的拷贝,基本规则如下:
- 1、 基本类型
- 如果变量是基本很类型,则拷贝其值,比如int、float等。
- 2、 对象
- 如果变量是一个实例对象,则拷贝其地址引用,也就是说此时新对象与原来对象是公用该实例变量。
- 3、 String字符串
- 若变量为String字符串,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有紫都城对象保持不变。
深复制的实现:
1 public ResumeDeepCopy clone() { 2 ExperienceDeepCopy experience=this.experience.Clone(); 3 return new ResumeDeepCopy(this.name,this.age,experience); 4 }
深复制首先需要在字段所用的引用类型的类中增加一个Clone方法。普通字段直接使用原有的字段新建对象,引用对象需要通过该对象的Clone方法先复制出一个新对象,再将这个新的引用字段来构造新的对象。
浅复制实现原型模式:
工作经验类 Experience
1 public class Experience{ 2 private String educationBackground; 3 private String skills; 4 5 public void setExperience(String educationBackground,String skills) { 6 this.educationBackground=educationBackground; 7 this.skills=skills; 8 } 9 10 @Override 11 public String toString() { 12 return educationBackground+skills; 13 } 14 } 15 }
简历类Resume
1 package PrototypePattern; 2 3 public class Resume implements Cloneable{ 4 private String name; 5 private int age; 6 private Experience experience; 7 public Resume(String name, int age) 8 { 9 this.name=name; 10 this.age=age; 11 this.experience=new Experience(); 12 } 13 public void setAge(int age) { 14 this.age = age; 15 } 16 17 public void setName(String name) { 18 this.name = name; 19 } 20 21 public void setExperience(String educationBackground,String skills) { 22 this.experience.setExperience(educationBackground,skills); 23 } 24 25 @Override 26 public String toString() { 27 return "name:"+name+" age:"+age+" experience:"+experience; 28 } 29 public Resume clone() { 30 try { 31 return (Resume) super.clone(); 32 } 33 catch (Exception e) 34 { 35 System.out.println(e); 36 return null; 37 } 38 39 } 40 }
主函数
1 public class Client { 2 public static void main(String[] args) { 3 //Copy 4 Resume resume=new Resume("test",20); 5 resume.setExperience("本科","C++"); 6 Resume resume2= resume.clone(); 7 System.out.println("resume and resume2"); 8 System.out.println(resume); 9 System.out.println(resume2); 10 System.out.println(); 11 System.out.println("resume and modified resume2"); 12 resume2.setAge(18); 13 resume2.setName("copy"); 14 resume2.setExperience("专科","C#"); 15 System.out.println(resume); 16 System.out.println(resume2); 17 } 18 }
结果:
可见当改变Experience时,也会改变原对象的值。
深复制实现原型模式:
经验类 ExperienceDeepCopy
1 public class ExperienceDeepCopy implements Cloneable{ 2 private String educationBackground; 3 private String skills; 4 5 public void setExperience(String educationBackground,String skills) { 6 this.educationBackground=educationBackground; 7 this.skills=skills; 8 } 9 10 @Override 11 public String toString() { 12 return educationBackground+skills; 13 } 14 public ExperienceDeepCopy Clone() 15 { 16 try { 17 return (ExperienceDeepCopy) super.clone(); 18 } 19 catch (Exception e) 20 { 21 e.printStackTrace(); 22 return null; 23 } 24 } 25 }
简历类 ResumeDeepCopy
1 public class ResumeDeepCopy{ 2 private String name; 3 private int age; 4 private ExperienceDeepCopy experience; 5 public ResumeDeepCopy(String name, int age) 6 { 7 this.name=name; 8 this.age=age; 9 this.experience=new ExperienceDeepCopy(); 10 } 11 private ResumeDeepCopy(String name, int age, ExperienceDeepCopy experience) 12 { 13 this.name=name; 14 this.age=age; 15 this.experience=experience; 16 } 17 public void setExperience(String educationBackground,String skills) { 18 this.experience.setExperience(educationBackground,skills); 19 } 20 public void setAge(int age) { 21 this.age = age; 22 } 23 24 public void setName(String name) { 25 this.name = name; 26 } 27 28 @Override 29 public String toString() { 30 return "name:"+name+" age:"+age+" experience:"+experience; 31 } 32 33 public ResumeDeepCopy clone() { 34 ExperienceDeepCopy experience=this.experience.Clone(); 35 return new ResumeDeepCopy(this.name,this.age,experience); 36 } 37 }
主函数
1 public class Client { 2 public static void main(String[] args) { 3 //DeepCopy 4 System.out.println(); 5 ResumeDeepCopy resumeDeepCopy=new ResumeDeepCopy("test",20); 6 resumeDeepCopy.setExperience("本科","C++"); 7 ResumeDeepCopy resumeDeepCopy2=resumeDeepCopy.clone(); 8 System.out.println("resumeDeepCopy and resumeDeepCopy2"); 9 System.out.println(resumeDeepCopy); 10 System.out.println(resumeDeepCopy2); 11 System.out.println(); 12 System.out.println("resumeDeepCopy and modified resumeDeepCopy2"); 13 resumeDeepCopy2.setAge(18); 14 resumeDeepCopy2.setName("copy"); 15 resumeDeepCopy2.setExperience("专科","C#"); 16 System.out.println(resumeDeepCopy); 17 System.out.println(resumeDeepCopy2); 18 } 19 }
结果截图
深复制与浅复制参考文章:https://www.cnblogs.com/qlky/p/7348353.html
原型模式相关代码:https://github.com/lancelee98/DesignPattern/tree/master/src/PrototypePattern
以上是关于设计模式之原型模式的主要内容,如果未能解决你的问题,请参考以下文章