大话设计模式之原型模式

原型模式

  是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

  这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

优点: 1、性能提高。 2、逃避构造函数的约束。

缺点: 1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。 2、必须实现 Cloneable 接口。

注意事项:与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。

     浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。 

具体实现

原型类

package com.chenpt.designModel.prototypeModel;

import java.io.Serializable;

/**
 * @Author: chenpengtao
 * @Description: 简历
 * @Date: created in 2018/8/1
 * @Modified By:
 */
public class Resume implements Cloneable,Serializable{
    private static final long serialVersionUID = 1L;

    private String name;
    private String sex;
    private String age;

    Resume(String name,String sex,String age){
        this.name=name;
        this.sex=sex;
        this.age=age;
    }

    /**
     * 设置个人信息
     * @param sex
     * @param age
     */
    public void setPersonInfo(String sex,String age){
        this.sex=sex;
        this.age=age;
    }

    //描述
    public void dispaly(){
        System.out.println("姓名:"+name+"\t年龄:"+age+"\t性别:"+sex);
    }

    public Object clone(){
        try {
            Resume resume = (Resume)super.clone();
            return resume;
        }catch (Exception e){
            return null;
        }

    }

}

  客户端

package com.chenpt.designModel.prototypeModel;

/**
 * @Author: chenpengtao
 * @Description:
 * @Date: created in 2018/8/1
 * @Modified By:
 */
public class MainTest {
    public static void main(String[] args){

        Resume resume = new Resume("大鸟","男","25");

        Resume resume2 = (Resume)resume.clone();
        resume2.setPersonInfo("男","26");

        resume.dispaly();
        resume2.dispaly();

    }
}
//结果
姓名:大鸟	年龄:25	性别:男
姓名:大鸟	年龄:26	性别:男

 如上代码基本实现了一个原型模式示例:

浅复制与深复制

  现在需求改了--我们需要新加入工作经历,那么修改上述代码

新加入工作类

package com.chenpt.designModel.prototypeModel;

/**
 * @Author: chenpengtao
 * @Description: 工作经历
 * @Date: created in 2018/8/1
 * @Modified By:
 */
public class WorkExperience{

    private String workDate;
    private String company;

    public WorkExperience(String workDate,String company){
        this.workDate=workDate;
        this.company=company;
    }

    public WorkExperience(){}

    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;
    }
    
}

 在个人信息那边引入工作类

package com.chenpt.designModel.prototypeModel;

import java.io.Serializable;

/**
 * @Author: chenpengtao
 * @Description: 简历
 * @Date: created in 2018/8/1
 * @Modified By:
 */
public class Resume implements Cloneable,Serializable{
    private static final long serialVersionUID = 1L;

    private String name;
    private String sex;
    private String age;
    private WorkExperience workExperience;

    Resume(String name,String sex,String age){
        this.name=name;
        this.sex=sex;
        this.age=age;
        this.workExperience=new WorkExperience();
    }

    /**
     * 设置个人信息
     * @param sex
     * @param age
     */
    public void setPersonInfo(String sex,String age){
        this.sex=sex;
        this.age=age;
    }

    /**
     * 设置工作经历
     * @param workDate
     * @param company
     */
    public void setWorkExperience(String workDate, String company){
        this.workExperience.setWorkDate(workDate);
        this.workExperience.setCompany(company);
    }

    //描述
    public void dispaly(){
        System.out.println("姓名:"+name+"\t年龄:"+age+"\t性别:"+sex);
        System.out.println("工作经历:"+workExperience.getWorkDate()+"\t"+workExperience.getCompany());
    }

    public Object clone(){
        try {
            Resume resume = (Resume)super.clone();
            return resume;
        }catch (Exception e){
            return null;
        }

    }

}

  客户端

package com.chenpt.designModel.prototypeModel;

/**
 * @Author: chenpengtao
 * @Description:
 * @Date: created in 2018/8/1
 * @Modified By:
 */
public class MainTest {
    public static void main(String[] args){

        Resume resume = new Resume("大鸟","男","25");
        resume.setWorkExperience("2015-2016","南京工作");

        Resume resume2 = (Resume)resume.clone();
        resume2.setPersonInfo("男","26");
        resume2.setWorkExperience("2016-2018","上海工作");

        resume.dispaly();
        resume2.dispaly();

    }
}
//执行结果
姓名:大鸟	年龄:25	性别:男
工作经历:2016-2018	上海工作
姓名:大鸟	年龄:26	性别:男
工作经历:2016-2018	上海工作

  咦!!!什么情况???怎么工作经历显示的是最后一次设置的值啊?

不要慌  问题不大。这是由于浅表复制导致的结果,对于值类型 克隆没问题,但对于引用类型来说,就只是复制了引用,引用的对象还是原来对象的地址,所以才有上述结果,既然已经说到这了就介绍下浅复制和深复制的概念吧

浅复制:被复制对象的所有变量都含有与原来对象相同的值,而所有的对其他对象是引用都仍然指向原来的对象。

深复制:就是把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

深复制演示示例

修改工作经历实现克隆

 

package com.chenpt.designModel.prototypeModel;

/**
 * @Author: chenpengtao
 * @Description: 工作经历
 * @Date: created in 2018/8/1
 * @Modified By:
 */
public class WorkExperience implements Cloneable{

    private String workDate;
    private String company;

    public WorkExperience(String workDate,String company){
        this.workDate=workDate;
        this.company=company;
    }

    public WorkExperience(){}

    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 Object clone(){
        try {
            return super.clone();
        }catch (Exception e){
            return null;
        }

    }

}

 

 修改resume对象

package com.chenpt.designModel.prototypeModel;

import java.io.Serializable;

/**
 * @Author: chenpengtao
 * @Description: 简历
 * @Date: created in 2018/8/1
 * @Modified By:
 */
public class Resume implements Cloneable,Serializable{
    private static final long serialVersionUID = 1L;

    private String name;
    private String sex;
    private String age;
    private WorkExperience workExperience;

    Resume(String name,String sex,String age){
        this.name=name;
        this.sex=sex;
        this.age=age;
        this.workExperience=new WorkExperience();
    }

    /**
     * 添加私有构造 克隆工作经历
     * @param workExperience
     */
    private Resume(WorkExperience workExperience){
        this.workExperience= (WorkExperience) workExperience.clone();
    }

    /**
     * 设置个人信息
     * @param sex
     * @param age
     */
    public void setPersonInfo(String sex,String age){
        this.sex=sex;
        this.age=age;
    }

    /**
     * 设置工作经历
     * @param workDate
     * @param company
     */
    public void setWorkExperience(String workDate, String company){
        this.workExperience.setWorkDate(workDate);
        this.workExperience.setCompany(company);
    }

    //描述
    public void dispaly(){
        System.out.println("姓名:"+name+"\t年龄:"+age+"\t性别:"+sex);
        System.out.println("工作经历:"+workExperience.getWorkDate()+"\t"+workExperience.getCompany());
    }

    /**
     * 重写了克隆方法
     * @return
     */
    public Object clone(){
        try {
            Resume resume = new Resume(this.workExperience);//调用私有构造器实现工作经历克隆
            //给对象属性重新赋值--最终返回的是深复制的resume对象
            resume.name=this.name;
            resume.sex=this.sex;
            resume.age=this.age;
            return resume;
        }catch (Exception e){
            return null;
        }

    }

}

  客户端

package com.chenpt.designModel.prototypeModel;

/**
 * @Author: chenpengtao
 * @Description:
 * @Date: created in 2018/8/1
 * @Modified By:
 */
public class MainTest {
    public static void main(String[] args){

        Resume resume = new Resume("大鸟","男","25");
        resume.setWorkExperience("2015-2016","南京工作");

        Resume resume2 = (Resume)resume.clone();
        resume2.setPersonInfo("男","26");
        resume2.setWorkExperience("2016-2018","上海工作");

        resume.dispaly();
        resume2.dispaly();

    }
}
//执行结果
姓名:大鸟	年龄:25	性别:男
工作经历:2015-2016	南京工作
姓名:大鸟	年龄:26	性别:男
工作经历:2016-2018	上海工作

  

 

 

 

 

 

 

posted @ 2018-08-23 15:20  不二尘  阅读(160)  评论(0编辑  收藏  举报