设计模式——原型模式

一、原型模式概述

        原型模式是一种特殊的创建型模式,它通过复制一个已有对象来获取更多相同或者相似的对象。原型模式可以提高相同类型对象的创建效率,简化创建过程。 

二、原型模式克隆机制

  • 浅克隆(Shallow Clone)

       浅克隆:如果原型对象的成员变量是值类型(如 int、double、byte、boolean、char等基本数据类型),将复制一份给克隆对象;如果原型对象的成员变量是引用类型(如类、接口、数组等复杂数据类型),则将引用对象的地址复制一份给克隆对象,也就是说克隆对象的成员变量指向相同的内存地址。简单来说,在浅克隆中,当原型对象被复制时只是复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制。

  • 深克隆(Deep Clone)

        深克隆:无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将被复制。

三、原型模式实现

  • 通用实现
public abstract class Prototype {
    public abstract Prototype clone();
}

class ConcretePrototype extends Prototype{

    private String attr;

    public String getAttr() {
        return attr;
    }

    public void setAttr(String attr) {
        this.attr = attr;
    }

    @Override
    public Prototype clone() {
        ConcretePrototype prototype = new ConcretePrototype();
        prototype.setAttr(this.attr);
        return prototype;
    }

    public static void main(String[] args) {
        ConcretePrototype prototype = new ConcretePrototype();
        prototype.setAttr("simple");
        Prototype clone = prototype.clone();
        System.out.println(prototype==clone);//false
    }
}
  • Java中的clone()方法和Cloneable接口(示例为浅克隆)
class ConcretePrototype implements Cloneable{

    private String attr;

    public String getAttr() {
        return attr;
    }

    public void setAttr(String attr) {
        this.attr = attr;
    }

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

    public static void main(String[] args) throws CloneNotSupportedException {
        ConcretePrototype prototype = new ConcretePrototype();
        prototype.setAttr("simple");
        ConcretePrototype clone = (ConcretePrototype)prototype.clone();
        System.out.println(prototype==clone);//false
        System.out.println("prototype:"+prototype+" hashcode:"+ prototype.hashCode());
        System.out.println("clone:"+clone+" hashcode:"+ clone.hashCode());
    }
}
  •  深克隆的实现(深克隆实现方式有多种,示例代码为推荐实现方法)
/**
 * 周报
 */
public class WeeklyLog implements Serializable, Cloneable {

    private Attachment attachment;

    private String name;

    private String date;

    private String content;

    public Attachment getAttachment() {
        return attachment;
    }

    public void setAttachment(Attachment attachment) {
        this.attachment = attachment;
    }

    public String getName() {
        return name;
    }

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

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    /**
     * 浅克隆
     */
    public WeeklyLog clone() {
        Object object = null;
        try {
            object = super.clone();//调用Object clone方法
            return (WeeklyLog) object;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 使用序列化技术实现深克隆
     */
    public WeeklyLog deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return (WeeklyLog) ois.readObject();
    }
}

/**
 * 附件
 */
class Attachment implements Serializable {
    private String name;

    public String getName() {
        return name;
    }

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

    public void download() {
        System.out.println("下载附件:文件名为:" + name);
    }
}

class Client {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Attachment attachment = new Attachment();
        attachment.setName("附件一");
        WeeklyLog weeklyLog = new WeeklyLog();
        weeklyLog.setName("测试");
        weeklyLog.setAttachment(attachment);
        //深克隆
        WeeklyLog clone = weeklyLog.deepClone();
        System.out.println(weeklyLog == clone);//false
        System.out.println(weeklyLog.getAttachment() == clone.getAttachment());//false
        //浅克隆
        WeeklyLog clone1 = weeklyLog.clone();
        System.out.println(weeklyLog == clone1);//false
        System.out.println(weeklyLog.getAttachment() == clone1.getAttachment());//true

    }
}

四、使用场景

  • 订单的复制(商品对象)。
  • 周报的复制(附件对象)。
  • spring中原型bean的创建。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值