读《设计模式:可复用面向对象软件的基础》--创建者模式之原型模式(Prototype)

原型模式

意图

用原型实例指定创建对象的种类,并且通过拷贝(注意深拷贝与浅拷贝)这些原型创建新的对象。

拷贝(克隆)

浅克隆(浅拷贝)

浅克隆(ShallowClone):也叫浅拷贝,在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址(一变都变)。

深克隆(深拷贝)

深克隆(DeepClone):也叫深拷贝,在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象(克隆对象的改变不影响原来对象)。

动机

有些对象的创建过程较为复杂,而且有时候需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。

结构

原型模式

参与者

参与者

适用场景

1、创建新对象成本较大(如初始化需要占用较长的时间,占用太多的CPU资源或网络资源),新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对其成员变量稍作修改。
2、需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。
3、原型模式也能够用来解决“仅仅知接口而不知实现的问题”,使用原型模式,能够出现一种独特的“接口造接口”的景象,这在面向接口编程中非常实用。

本质

克隆生成对象。克隆是手段。目的还是生成新的对象实例。

优点

  1. 性能高 : 使用原型模式复用的方式创建实例对象 , 比使用构造函数重新创建对象性能要高 ; ( 针对类实例对象开销大的情况 )
  2. 流程简单 : 原型模式可以简化创建的过程 , 可以直接修改现有的对象实例的值 , 达到复用的目的 ; ( 针对构造函数繁琐的情况 )

缺点

  1. 覆盖 clone 方法 ( 必须 ) : 必须重写对象的 clone 方法 , Java 中提供了 cloneable 标识该对象可以被拷贝 , 但是必须覆盖 Object 的 clone 方法才能被拷贝 ;
  2. 深拷贝 与 浅拷贝 风险 : 克隆对象时进行的一些修改 , 容易出错 ; 需要灵活运用深拷贝与浅拷贝操作

通过简历案例说明原型模式

/**
* 场景:我们需要很多份简历,简历信息可以不相同也可以相同。
* 第一步:创建简历原型Resume类,重写克隆方法
* 第二步:客户端测试通过克隆创建新对象
* 有引用类型数据要用深拷贝
*/
//创建简历原型Resume类,重写克隆方法
public class ResumePrototype implements Cloneable{
    private String name;
    private Address address;

    public ResumePrototype(String name) {
        this.name = name;
        this.address = new Address();
    }
    private ResumePrototype(Address address) throws CloneNotSupportedException {
        this.address = (Address) address.clone();
    }

    public void setAddress(String add) {
        address.setAdd(add);
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //引用也进行了拷贝
        ResumePrototype obj = new ResumePrototype(this.address);
        obj.name = this.name;
        return obj;
    }

    @Override
    public String toString() {
        return "ResumePrototype{" +
                "name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}
public class Address implements Cloneable{
    private String add;
    public void setAdd(String add) {
        this.add = add;
    }
    @Override
    public String toString() {
        return "Address{" +
                "add='" + add + '\'' +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
//第二步:测试
public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        ResumePrototype resume1  = new ResumePrototype("liming");
        resume1.setAddress("china");
        ResumePrototype resume2 = (ResumePrototype) resume1.clone();
        resume2.setAddress("Russia");
        System.out.println(resume1);
        System.out.println(resume2);
    }
}
//结果
ResumePrototype{name='liming', address=Address{add='china'}}
ResumePrototype{name='liming', address=Address{add='Russia'}}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w͏l͏j͏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值