初学《大话设计模式》——原型模式

一、概述

1、定义
原型模式,用原型示例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

2、结构图
这里写图片描述

原型模式其实就是从一个对象创建另外一个可定制的对象,而且不需要知道任何创建的细节。

二、实现方式

1、调用api

 protected native Object clone() throws CloneNotSupportedException;

说明:需要重写Object类的clone方法

2、使用方式
如果要克隆一个类的实例,这个类必须:

  • 实现Cloneable接口。
  • 使用public访问修饰符重新定义clone方法

注:使用clone方法对一个对象进行克隆时,默认是对该对象进行浅复制的,而在开发中通常需要对对象进行深复制。
浅复制:若要克隆的对象的成员变量是数值或基本类型,则直接将成员变量的值复制一份;若成员变量是引用类型,则只复制成员变量的引用地址,即复制后的成员变量与原变量引用同一个对象(若成员变量是不可变的引用类型如String,则情况与基本类型一样)。
深复制:无论是基本类型或是引用类型,都将成员变量的引用的对象复制一遍,复制后的变量引用新的对象。

三、代码实现

1、场景
用代码实现简历的复制,简历中包含个人信息和工作经历

2、代码清单
这里写图片描述

3、浅复制

package prototype.light;

/**
* @ClassName: WorkExperience
* @Description: 工作经历类
* @author kooking
* @date 2018-7-3 下午8:17:36
*/ 
public class WorkExperience{
    private String workDate;
    private String company;
    public String getWorkDate() {
        return workDate;
    }
    public void setWorkDate(String workDate) {
        this.workDate = workDate;
    }
    public String getCompany() {
        return company;
    }
    public void setCompany(String company) {
        this.company = company;
    }
    public WorkExperience(String workDate, String company) {
        super();
        this.workDate = workDate;
        this.company = company;
    }
    public WorkExperience() {

    }




}
package prototype.light;

/**
* @ClassName: Resume
* @Description: 简历类(浅复制)
* @author kooking
* @date 2018-7-3 下午8:22:25
*/ 
public class Resume implements Cloneable {

    private String name;
    private String sex;
    private String age;
    private WorkExperience work;

    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 String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
    public WorkExperience getWork() {
        return work;
    }
    public void setWork(WorkExperience work) {
        this.work = work;
    }



    public Resume() {

    }
    public Resume(String name, String sex, String age, WorkExperience work) {
        super();
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.work = work;
    }
    public void  display(){
        System.out.println(name+" ,"+sex+","+age);
        System.out.println("工作经历:"+work.getWorkDate()+" "+work.getCompany());
    }


    /* (non-Javadoc)
    * Title: clone
    * Description: 重写clone方法
    * @return
    * @throws CloneNotSupportedException
    * @see java.lang.Object#clone()
    */ 
    @Override
    public Resume clone() throws CloneNotSupportedException {

        return (Resume) super.clone();
    }
}
package prototype.light;

/**
* @ClassName: LightClone
* @Description: 浅复制测试类
* @author kooking
* @date 2018-7-3 下午8:50:44
*/ 
public class LightClone {

    public static void main(String[] args) throws Exception{

        //原型
        Resume originalResume=new Resume("大鸟","男","29",new WorkExperience("1998-2000", "xx公司"));

        //由原型克隆出来的A简历
        Resume cloneA= originalResume.clone();
        cloneA.getWork().setWorkDate("1998-2006");
        cloneA.getWork().setCompany("yy公司");

        // 由原型克隆出来的B简历
        Resume cloneB = originalResume.clone();
        cloneB.getWork().setWorkDate("1998-2003");
        cloneB.getWork().setCompany("zz公司");

        originalResume.display();
        cloneA.display();
        cloneB.display();

        //查看对象
        System.out.println(originalResume+"--"+originalResume.getWork());
        System.out.println(cloneA+"--"+cloneA.getWork());
        System.out.println(cloneB+"--"+cloneB.getWork());
    }

}

测试结果

大鸟 ,男,29
工作经历:1998-2003 zz公司
大鸟 ,男,29
工作经历:1998-2003 zz公司
大鸟 ,男,29
工作经历:1998-2003 zz公司
prototype.light.Resume@1db05b2--prototype.light.WorkExperience@530cf2
prototype.light.Resume@76fba0--prototype.light.WorkExperience@530cf2
prototype.light.Resume@181ed9e--prototype.light.WorkExperience@530cf2

4、深复制

package prototype.deep;

/**
* @ClassName: WorkExperience_Deep
* @Description: 工作经历类(深复制)
* @author kooking
* @date 2018-7-3 下午9:03:03
*/ 
public class WorkExperience_Deep implements Cloneable{

    private String workDate;
    private String company;
    public String getWorkDate() {
        return workDate;
    }
    public void setWorkDate(String workDate) {
        this.workDate = workDate;
    }
    public String getCompany() {
        return company;
    }
    public void setCompany(String company) {
        this.company = company;
    }
    public WorkExperience_Deep(String workDate, String company) {
        super();
        this.workDate = workDate;
        this.company = company;
    }
    public WorkExperience_Deep() {

    }

    /* (non-Javadoc)
    * Title: clone
    * Description: 重写clone方法
    * @return
    * @throws CloneNotSupportedException
    * @see java.lang.Object#clone()
    */ 
    @Override
    public WorkExperience_Deep clone() throws CloneNotSupportedException {

        return (WorkExperience_Deep) super.clone();
    }
}
package prototype.deep;


/**
* @ClassName: Resume_Deep
* @Description: 简历类(深复制)
* @author kooking
* @date 2018-7-3 下午8:54:16
*/ 
public class Resume_Deep implements Cloneable {
    private String name;
    private String sex;
    private String age;
    private WorkExperience_Deep work;

    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 String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
    public WorkExperience_Deep getWork() {
        return work;
    }
    public void setWork(WorkExperience_Deep work) {
        this.work = work;
    }



    public Resume_Deep() {

    }
    public Resume_Deep(String name, String sex, String age, WorkExperience_Deep work) {
        super();
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.work = work;
    }
    public void  display(){
        System.out.println(name+" ,"+sex+","+age);
        System.out.println("工作经历:"+work.getWorkDate()+" "+work.getCompany());
    }


    /* (non-Javadoc)
    * Title: clone
    * Description: 重写clone方法
    * @return
    * @throws CloneNotSupportedException
    * @see java.lang.Object#clone()
    */ 
    @Override
    public Resume_Deep clone() throws CloneNotSupportedException {
        Resume_Deep resume=(Resume_Deep) super.clone();
         resume.work=(WorkExperience_Deep) this.work.clone();
         return resume;
    }
}
package prototype.deep;


/**
* @ClassName: DeepClone
* @Description: 深复制测试类
* @author kooking
* @date 2018-7-3 下午9:11:53
*/ 
public class DeepClone {

    public static void main(String[] args) throws CloneNotSupportedException {

        //原型
        Resume_Deep originalResume=new Resume_Deep("大鸟","男","29",
                new WorkExperience_Deep("1998-2000", "xx公司"));

        //由原型克隆出来的A简历
        Resume_Deep cloneA=originalResume.clone();
        cloneA.getWork().setWorkDate("1998-2006");
        cloneA.getWork().setCompany("yy公司");

        // 由原型克隆出来的B简历
        Resume_Deep cloneB =  originalResume.clone();
        cloneB.getWork().setWorkDate("1998-2003");
        cloneB.getWork().setCompany("zz公司");

        originalResume.display();
        cloneA.display();
        cloneB.display();

        //查看对象
        System.out.println(originalResume+"--"+originalResume.getWork());
        System.out.println(cloneA+"--"+cloneA.getWork());
        System.out.println(cloneB+"--"+cloneB.getWork());
    }
}

测试结果

大鸟 ,男,29
工作经历:1998-2000 xx公司
大鸟 ,男,29
工作经历:1998-2006 yy公司
大鸟 ,男,29
工作经历:1998-2003 zz公司
prototype.deep.Resume_Deep@18b3364--prototype.deep.WorkExperience_Deep@1db05b2
prototype.deep.Resume_Deep@530cf2--prototype.deep.WorkExperience_Deep@76fba0
prototype.deep.Resume_Deep@181ed9e--prototype.deep.WorkExperience_Deep@1175422

四、总结

1、优点
简化对象创建过程,提高效率。

2、缺点
实现深复制时可能需要比较复杂的代码。

3、适用场景
原型模式通常在以下情况使用:
通过其构造方法创建一个对象需要耗时很久或者消耗很多资源时,可以考虑使用原型模式。
(使用clone方法创建对象不需要调用其构造方法,它的本质是在内存中复制对象)

猜你喜欢

转载自blog.csdn.net/KooKing_L/article/details/80910085
今日推荐