设计模式 之 原型模式

设计模式 之 原型模式

描述

通过复制现有的对象实例来创建新的对象实例。

使用场景

  • 需要clone对象
  • 创建对象的成本比较大

实现步骤

1、想要支持对象的clone,对象需要实现 Cloneable
2、并且重写 clone() 方法

代码案例

package com.foruo.learn.designmode.cloneable;

/**
 * 案例对象
 *
 * 想要支持对象的clone,对象需要实现 Cloneable
 * 并且重写 clone() 方法
 *
 * @author GaoYuan
 * @date 2018/5/14 上午8:54
 */
public class DemoEntity implements Cloneable{

    private String id;
    private String name;
    private String msg;

    public DemoEntity(String msg){
        this.msg = msg;
    }

    public DemoEntity(){}
    
    /**
     * 执行clone
     * 注意,需要考虑到 浅拷贝 与 深拷贝 的情况
     * @author GaoYuan
     * @date 2018/5/14 上午8:56
     */
    @Override
    protected DemoEntity clone(){
        DemoEntity demoEntity = null;
        try{
            demoEntity = (DemoEntity)super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return demoEntity;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "DemoEntity{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", msg='" + msg + '\'' +
                '}';
    }
}

测试代码

package com.foruo.learn.designmode.cloneable;

/**
 * 原型 clone写法
 * @author GaoYuan
 * @date 2018/5/14 上午8:51
 */
public class TestMain {

    public static void main(String[] args){
        //填写相同不变的数据
        DemoEntity demoEntity = new DemoEntity("消息内容");
        DemoEntity demo;
        int i = 0;
        while(i<10){
            //执行clone,并填写变化的数据
            demo = demoEntity.clone();
            demo.setId(""+i);
            demo.setName("高元"+i);
            System.out.println(demo);
            i++;
        }
    }
}

优缺点

优点:
  • 原型模型比直接new一个对象效率高,因为操作的是内存中的二进制流,当复制大对象时,性能的差别就比较明显了。
  • 可以循环外预先赋值相同的属性值,而不用循环中重复赋值;
缺点:
  • 使用原型模式时不能有final对象。
  • Object类的clone方法只会拷贝对象中的基本数据类型,对于数组,引用对象等只能另行拷贝。(需要进行深拷贝)

JDK中的使用场景

例如:

javax.servlet.http.Cookie

package javax.servlet.http;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

public class Cookie implements Cloneable, Serializable {
    
    /**省略了其余代码*/
  
    public Cookie(String name, String value) {
        if (name == null || name.length() == 0) {
            throw new IllegalArgumentException(
                    lStrings.getString("err.cookie_name_blank"));
        }
        if (!isToken(name) ||
                name.equalsIgnoreCase("Comment") || // rfc2019
                name.equalsIgnoreCase("Discard") || // 2019++
                name.equalsIgnoreCase("Domain") ||
                name.equalsIgnoreCase("Expires") || // (old cookies)
                name.equalsIgnoreCase("Max-Age") || // rfc2019
                name.equalsIgnoreCase("Path") ||
                name.equalsIgnoreCase("Secure") ||
                name.equalsIgnoreCase("Version") ||
                name.startsWith("$")) {
            String errMsg = lStrings.getString("err.cookie_name_is_token");
            Object[] errArgs = new Object[1];
            errArgs[0] = name;
            errMsg = MessageFormat.format(errMsg, errArgs);
            throw new IllegalArgumentException(errMsg);
        }

        this.name = name;
        this.value = value;
    }

    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

}

可以看到最核心的几处地方

  • 实现了 Cloneable
  • 重写了 clone()
  • 也有个和我们写的案例差不多的有参数的构造器

码云

https://gitee.com/gmarshal/foruo-learn-java/tree/master/src/main/java/com/foruo/learn/designmode/cloneable

博客

https://my.oschina.net/gmarshal/blog/1811901

欢迎关注我的个人微信订阅号:(据说这个头像程序猿专用)

输入图片说明

转载于:https://my.oschina.net/gmarshal/blog/1811901

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值