美文网首页
原型模式

原型模式

作者: 定金喜 | 来源:发表于2020-05-23 19:48 被阅读0次

由于 Java 提供了对象的 clone() 方法,所以用 Java 实现原型模式很简单。

1. 模式的结构

原型模式包含以下主要角色。

  1. 抽象原型类:规定了具体原型对象必须实现的接口。
  2. 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  3. 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

其结构图如图 1 所示。

原型模式的结构图

2. 实现深拷贝的几种方法

2.1 clone方法

@Data
public class Company implements Cloneable{

    /**
     * 公司唯一标识
     */
    private String companyId;

    /**
     * 公司名称
     */
    private String companyName;

    /**
     * 成立时间
     */
    private Date startDate;

    /**
     * 行业
     */
    private String industry;

    /**
     * 员工列表
     */
    private List<Colleague> colleagueList;

    @Override
    public Company clone(){
        Company newCompany = null;
        try {
            newCompany = (Company)super.clone();
            List<Colleague> newColleagueList = new ArrayList<>();
            for (Colleague colleague : colleagueList) {
                newColleagueList.add((Colleague)colleague.clone());
            }
            newCompany.setColleagueList(newColleagueList);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return newCompany;
    }
    
}
@Data
public class Colleague implements Cloneable{

    /**
     * 工号
     */
    private String jobNumber;

    /**
     * 姓名
     */
    private String userName;

    /**
     * 生日
     */
    private Date birthday;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 薪资
     */
    private Double salary;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

2.2 json
通过fastjson实现

@Data
public class Company implements Cloneable{

    public Company(String companyId, String companyName, String industry, List<Colleague> colleagueList) {

        this.companyId = companyId;
        this.companyName = companyName;
        this.industry = industry;
        this.colleagueList = colleagueList;
    }

    public Company(){

    }

    /**
     * 公司唯一标识
     */
    private String companyId;

    /**
     * 公司名称
     */
    private String companyName;

    /**
     * 成立时间
     */
    private Date startDate;

    /**
     * 行业
     */
    private String industry;

    /**
     * 员工列表
     */
    private List<Colleague> colleagueList;

    @Override
    public Company clone(){
        Company newCompany = null;
        try {
            newCompany = (Company)super.clone();
            List<Colleague> newColleagueList = new ArrayList<>();
            for (Colleague colleague : colleagueList) {
                newColleagueList.add((Colleague)colleague.clone());
            }
            newCompany.setColleagueList(newColleagueList);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return newCompany;
    }

    public static void main(String[] args) {

        List<Colleague> colleagueList = new ArrayList<>();
        colleagueList.add(new Colleague("123","晓明"));
        colleagueList.add(new Colleague("456","baby"));
        Company sourceCompany = new Company("12345", "企查查", "查询",colleagueList);
        Company targetCompany = JSON.parseObject(JSON.toJSONString(sourceCompany), Company.class);
        System.out.println("sourceCompany:"+JSON.toJSONString(sourceCompany)
                +",targetCompany:"+JSON.toJSONString(targetCompany)
                +",sourceCompany == targetCompany:"+(sourceCompany == targetCompany));
        System.out.println("colleagueList:"+JSON.toJSONString(colleagueList)
                        +",newColleagueList:"+targetCompany.colleagueList
                        +",colleagueList == newColleagueList:"+(colleagueList == targetCompany.colleagueList));
    }
}
@Data
public class Colleague implements Cloneable{

    public Colleague(String jobNumber, String userName) {
        this.jobNumber = jobNumber;
        this.userName = userName;
    }

    public Colleague(){

    }

    /**
     * 工号
     */
    private String jobNumber;

    /**
     * 姓名
     */
    private String userName;

    /**
     * 生日
     */
    private Date birthday;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 薪资
     */
    private Double salary;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

输出:

sourceCompany:{"colleagueList":[{"jobNumber":"123","userName":"晓明"},{"jobNumber":"456","userName":"baby"}],"companyId":"12345","companyName":"企查查","industry":"查询"},targetCompany:{"colleagueList":[{"jobNumber":"123","userName":"晓明"},{"jobNumber":"456","userName":"baby"}],"companyId":"12345","companyName":"企查查","industry":"查询"},sourceCompany == targetCompany:false
colleagueList:[{"jobNumber":"123","userName":"晓明"},{"jobNumber":"456","userName":"baby"}],newColleagueList:[Colleague(jobNumber=123, userName=晓明, birthday=null, age=null, salary=null), Colleague(jobNumber=456, userName=baby, birthday=null, age=null, salary=null)],colleagueList == newColleagueList:false

拷贝的对象与原来对象属性值一样,但是不指向同一内存区域

2.3 序列化和反序列化
Company和Colleague都实现Serializable接口

List<Colleague> colleagueList = new ArrayList<>();
        colleagueList.add(new Colleague("123","晓明"));
        colleagueList.add(new Colleague("456","baby"));
        Company sourceCompany = new Company("12345", "企查查", "查询",colleagueList);
        Company targetCompany = null;
        try
        {
            ByteArrayOutputStream bos = null;
            ObjectOutputStream oos = null;
            try
            {
                bos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(bos);
                oos.writeObject(sourceCompany);
                oos.flush();
            }
            finally
            {
                oos.close();
            }
            byte[] bytes = bos.toByteArray();
            ObjectInputStream ois = null;
            try
            {
                ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
                targetCompany = (Company)ois.readObject();
            }
            finally
            {
                ois.close();
            }

            System.out.println("sourceCompany:"+JSON.toJSONString(sourceCompany)
                    +",targetCompany:"+JSON.toJSONString(targetCompany)
                    +",sourceCompany == targetCompany:"+(sourceCompany == targetCompany));
            System.out.println("colleagueList:"+JSON.toJSONString(colleagueList)
                    +",newColleagueList:"+targetCompany.colleagueList
                    +",colleagueList == newColleagueList:"+(colleagueList == targetCompany.colleagueList));
        }
        catch(Exception e)
        {
            e.printStackTrace();//克隆失败
        }

2.4 工具类

 List<Colleague> colleagueList = new ArrayList<>();
        colleagueList.add(new Colleague("123","晓明"));
        colleagueList.add(new Colleague("456","baby"));
        Company sourceCompany = new Company("12345", "企查查", "查询",colleagueList);
        Company targetCompany = new Company();

        BeanUtils.copyProperties(sourceCompany, targetCompany);

        System.out.println("sourceCompany:"+JSON.toJSONString(sourceCompany)
                +",targetCompany:"+JSON.toJSONString(targetCompany)
                +",sourceCompany == targetCompany:"+(sourceCompany == targetCompany));
        System.out.println("colleagueList:"+JSON.toJSONString(colleagueList)
                +",newColleagueList:"+targetCompany.colleagueList
                +",colleagueList == newColleagueList:"+(colleagueList == targetCompany.colleagueList));

这个方法只能实现浅拷贝,不能实现深拷贝

相关文章

  • 第3章 创建型模式-原型模式

    一、原型模式简介 二、原型模式的优点 ■ 三、原型模式的使用场景 ■ 四、原型模式的实例

  • 设计模式之原型模式(Prototype 模式)

    引入原型模式 原型模式的实例 为什么需要使用原型模式 引入原型模式 如果读者很熟悉javascript的话,对原型...

  • 初始设计模式之原型模式

    原型模式是什么? 原型模式怎么用?浅拷贝深拷贝 原型模式再理解 一、原型模式是什么? ​ 原型模式是一种创建型设计...

  • 设计模式之原型模式(创建型)

    [TOC] 模式定义 原型模式(Prototype Pattern):原型模式是提供一个原型接口,提供原型的克隆,...

  • 原型模式C++

    原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 原型模式结构图 原型模式基本代码 原型...

  • 设计模式:原型

    原型模式基本介绍原型模式的实现源码中的原型模式记录 原型模式基本介绍 定义:用原型实例指定创建对象的种类,并通过复...

  • js集成

    原始继承模式--原型链 2:借用构造函数 3:共享构造原型 4:圣杯模式原型链; 构造函数; 共享原型; 圣杯模式...

  • 关于JavaScript创建对象的多种方式

    JavaScript创建对象的方法 工厂模式 构造函数模式 原型模式 组合使用构造函数模式和原型模式 动态原型模式...

  • 前端面试题总结【37】:javascript对象的几种创建方式

    工厂模式 构造函数模式 原型模式 混合构造函数和原型模式 动态原型模式 寄生构造函数模式 稳妥构造函数模式 推荐:...

  • 设计模式之原型模式

    原型模式 原型模式(prototype)是指原型实例指向对象的种类,并且通过拷贝这些原型创建新的对象 模式作用: ...

网友评论

      本文标题:原型模式

      本文链接:https://www.haomeiwen.com/subject/wxakahtx.html