【设计模式】第7章·原型模式

一、原型模式概述

原型模式:适用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。

二、原型模式结构与实现

2.1 原型模式结构

原型模式包含以下3个角色:

  1. Prototype(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,它可以是抽象类也可以是接口,甚至还可以是具体实现类。
  2. ConcretePrototype(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
  3. Client(客户类):在客户类中,让一个原型对象克隆自身从而创建一个新的对象。

2.2 浅克隆和深克隆

根据在复制原型对象的同时,是否复制包含在原型对象中引用类型的成员变量,原型模式的克隆机制分为两种,即浅克隆和深克隆。

浅克隆,当原型对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有被复制。

深克隆,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象。

2.3 原型模式实现

实现的demo代码如下。


/**
 * 原型对象类
 */
public class Customer implements Cloneable, Serializable {

    private String name;
    private Integer age;

    private Address address;


    //浅拷贝
    public Customer clone() {
        try {
            return (Customer) super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }

    //深拷贝,使用序列化技术
    public Customer deepClone() throws IOException, ClassNotFoundException {

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOs = new ObjectOutputStream(outputStream);
        objectOs.writeObject(this);

        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        ObjectInputStream objectInput = new ObjectInputStream(inputStream);
        return (Customer)objectInput.readObject();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}


//模拟地址信息的model
public class Address implements Serializable {

    private String path;//地址

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

客户端代码:

public class Client {

    public static void main(String[] args) {

        /**
         * 原型模式的demo:
         *
         * 原型类Customer,有一个引用类型的Address
         * 浅拷贝对引用类型是用的同一个地址引用;
         * 深拷贝对所有成员数据都是复制新的。
         *
         */

        //原型对象
        Address address = new Address();
        address.setPath("广东省深圳市南山区粤海街道");

        Customer customer = new Customer();
        customer.setName("tom");
        customer.setAge(19);
        customer.setAddress(address);

        //浅拷贝
        Customer clone = customer.clone();
        System.out.println(customer == clone);
        System.out.println(customer.getClass() == clone.getClass());
        System.out.println(customer.getAddress() == clone.getAddress());

        //深拷贝
        Customer deepClone = null;
        try {
            deepClone = customer.deepClone();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("克隆失败");
        }
        System.out.println(customer == deepClone);
        System.out.println(customer.getClass() == deepClone.getClass());
        System.out.println(customer.getAddress() == deepClone.getAddress());

    }
}

三、原型模式优缺点和适用环境

3.1 原型模式优点

  1. 当创建的对象实例比较复杂或者需要成本较大时,可以简化对象的创建过程,复制一个已有的实例可以提高新实例的创建效率;
  2. 扩展性较好。

3.2 原型模式缺点

  1. 需要为每一个类配备一个克隆方法,对已存在的类进行改造时比较麻烦,需要修改源代码,违背了开闭原则;
  2. 在实现深克隆时需要编写较为复杂的代码。

3.3 适用环境

  1. 创建新对象的成本比较大(例如初始化需要占用较长的时间,占用太多的CPU资源或网络资源);
  2. 系统要保存对象的状态,而对象的状态变化很小;
  3. 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态。

【参考文献】:
本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。

【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值