设计模式之原型模式

简介: 本篇文章是设计模式专题的第六篇文章,我会将遇到的设计模式都一一总结在该专题下,我会把自己对每一种设计模式的感悟写下来,以及在实际工作中我们该如何去灵活应用这些设计模式,欢迎大家关注。本篇文章我们就来讲一讲,用于创建重复对象的原型模式。

原型模式的简单介绍

原型模式也属于创建型模式的一种,它是用来创建重复对象的,也就是我们常说的拷贝对象。

原型模式是通过实现一个原型接口,然后调用clone()就可以完成对象复制,需要注意的是clone()方法是Object提供的,当需要深拷贝的时候,就需要通过重写克隆方法进行对象的拷贝。

原型模式类图:

image.png

原型模式扩展:

原型模式可以进行扩展,在原有的基础上增加一个原型管理器 PrototypeManager 类。该类用 HashMap 缓存多个复制的原型,客户端可以通过管理器的 get(String id) 方法从中获取复制的原型。

image.png

浅拷贝与深拷贝:

  • 浅拷贝:不重写clone方法的都是浅拷贝,浅拷贝如果对象内属性是引用类型的话,拷贝的是引用对象的地址。
  • 深拷贝:深拷贝需要重写clone方法,通过串行话或者其他方式将属性是引用类型的创建空间拷贝一份独立的。

原型模式的具体实现思路

  • 浅拷贝:直接实现Cloneable接口即可
  • 深拷贝:需要实现Cloneable接口,并且需要重写clone方法。
  • 原型管理器:

    • 创建抽象原型对象,继承Cloneable接口
    • 创建抽象原型对象的具体实现
    • 创建原型管理器,初始化缓存,提供获取拷贝对象的方法

原型模式的具体实现方案

  • 浅拷贝

    public class Prototype implements Cloneable {
        @Override
        public Object clone()  throws CloneNotSupportedException {
            return super.clone();
        }
    }
  • 深拷贝

    深拷贝的方式有很多,我们的目的是为了将引用类型重新开辟空间,而不是引用原引用的地址。

    // 实现的方式有很多,针对属性进行再次拷贝赋值,或者使用序列化
    // 1. 再次拷贝
    public class Prototype implements Cloneable {
        private OtherPrototype other;
        
        @Override
        public Object clone()  throws CloneNotSupportedException {
            Object obj = super.clone();
            // 将原引用的内容,重新开辟空间保存一份,使用新的引用
            obj.setOther((OtherPrototype) obj.getOther.clone());
            return obj;
        }
    }
    // 2. 序列化实现 注意需要实现Serializable
    public class Prototype implements Serializable {
        public Object deepClone() throws Exception
        {
            // 序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            // 反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return ois.readObject();
        }
    }
  • 原型管理器方式

    // 抽象原型对象
    public interface Prototype extends Cloneable {
        @Override
        public Object clone();
    }
    // 真实原型对象
    public class Realizetype implements Prototype {
        @Override
        public Object clone()  throws CloneNotSupportedException {
            return super.clone();
        }
    }
    // 原型管理器
    class ProtoTypeManager {
        // 缓存
        private HashMap<String, Object> cache = new HashMap<String, Object>();
        
        // 初始化缓存
        public ProtoTypeManager() {
            cache.put("realizetype", new Realizetype());
        }
        
        // 向缓存中添加原型对象
        public void addProtoType(String key, Object obj) {
            cache.put(key, obj);
        }
        // 获取对应原型对象的拷贝对象
        public Prototype getPrototype(String key) {
            Object temp = cache.get(key);
            return (Prototype) temp.clone();
        }
    }

原型模式的优缺点

优点

  • 原型模式性能很好,基于二进制的流复制比new性能更好。
  • 原型模式可以避免构造函数的约束。
  • Java 为我们将原型模式封装好,我们使用很方便。

缺点

  • 当需要深拷贝时,一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候,拷贝会变的很困难。
  • 必须实现 Cloneable 接口。
  • clone方法位于类的内部,如果需要对已有类进行改造,需要改变类的内部结构,违背了开闭原则。

原型模式的适用场景

  1. 对象之间相同或相似,只是个别的几个属性不同的时候。
  2. 创建对象成本较大,比如初始化时间长,占用CPU资源多,占用网络资源多等,需要优化资源。
  3. 创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性。
  4. 系统中大量使用该类对象,需要各个调用者给它的属性重新赋值。
  5. 当一个对象需要提供给其他对象访问,并且各个调用者都需要修改其值时。
  6. 原型模式很少单独出现,一般是伴随工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。

原型模式总结

原型模式虽然实现起来比较简单,用法也很简单。但是深拷贝和浅拷贝的问题我们一定要搞清楚,有时候使用浅拷贝导致数据混乱,排查起来也是很困难。再就是我们要善用原型管理器,通过原型管理器创建克隆对象会使我们事半功倍。

目录
相关文章
|
5月前
|
设计模式 安全 Java
面向对象编程的精髓:Java设计模式 - 原型模式(Prototype)完全参考手册
【4月更文挑战第7天】原型模式是OOP中的创建型设计模式,用于通过复制现有实例创建新实例,尤其适用于创建成本高或依赖其他对象的情况。它包括Prototype接口、ConcretePrototype实现和Client客户端角色。优点是性能优化、避免子类化和动态增加产品族。实现包括定义原型接口、实现具体原型和客户端调用克隆方法。最佳实践涉及确保克隆正确性、选择深拷贝或浅拷贝及考虑线程安全。但需注意克隆方法管理、性能开销和循环引用等问题。在Java中,实现Cloneable接口和覆盖clone方法可实现原型模式。
69 4
|
5月前
|
设计模式 Java 关系型数据库
23种设计模式 —— 原型模式【克隆羊、浅拷贝、深拷贝】
23种设计模式 —— 原型模式【克隆羊、浅拷贝、深拷贝】
|
5月前
|
设计模式 安全 Java
【设计模式】原型模式
【设计模式】原型模式
|
1月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
1月前
|
设计模式 Java
Java设计模式-原型模式(3)
Java设计模式-原型模式(3)
Java设计模式-原型模式(3)
|
3月前
|
设计模式
iLogtail设计模式问题之iLogtail中的原型模式是什么
iLogtail设计模式问题之iLogtail中的原型模式是什么
iLogtail设计模式问题之iLogtail中的原型模式是什么
|
3月前
|
设计模式 JavaScript
js设计模式【详解】—— 原型模式
js设计模式【详解】—— 原型模式
47 6
|
4月前
|
设计模式 Java
Java设计模式之原型模式详解
Java设计模式之原型模式详解
|
4月前
|
设计模式
原型模式-大话设计模式
原型模式-大话设计模式
|
4月前
|
设计模式 Java Spring
设计模式——原型模式
设计模式——原型模式