设计模式之原型模式

原型模式——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

   

原文地址:https://www.cnblogs.com/lancelee98/p/10285535.html