技术成神之路:设计模式(三)原型模式

1. 定义


原型模式(Prototype Pattern)是一种创建型设计模式,旨在通过复制现有对象来创建新对象,而不是通过实例化类的方式。这个模式可以提高对象创建的效率,尤其是在创建对象的过程非常复杂或代价高昂时。

2. 结构


原型模式包含以下角色:

  • Prototype(原型接口):用于声明克隆自身的方法。通常这个接口会定义一个名为clone的抽象方法。
  • ConcretePrototype(具体原型类):实现原型接口,并实现克隆自身的方法。这类对象可以被克隆。
  • Client(客户端):使用原型接口来克隆新的对象。

UML类图:

3. 示例代码


java 复制代码
// 原型接口
interface Prototype extends Cloneable {
    Prototype clone();
}

// 具体原型类A
class ConcretePrototypeA implements Prototype {
    private String name;

    public ConcretePrototypeA(String name) {
        this.name = name;
    }

    @Override
    public Prototype clone() {
        try {
            return (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String toString() {
        return "ConcretePrototypeA{name='" + name + "'} hashcode= "+ hashCode();
    }
}

// 具体原型类B
class ConcretePrototypeB implements Prototype {
    private int value;

    public ConcretePrototypeB(int value) {
        this.value = value;
    }

    @Override
    public Prototype clone() {
        try {
            return (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String toString() {
        return "ConcretePrototypeB{value=" + value + "} hashcode= "+ hashCode();
    }
}

测试:

java 复制代码
@Test
    public void test() {
        ConcretePrototypeA prototypeA = new ConcretePrototypeA("Prototype A");
        ConcretePrototypeB prototypeB = new ConcretePrototypeB(42);

        Prototype clonedPrototypeA = prototypeA.clone();
        Prototype clonedPrototypeB = prototypeB.clone();

        System.out.println("原型A: "+prototypeA);
        System.out.println("克隆A: "+clonedPrototypeA);
        System.out.println("原型B: "+prototypeB);
        System.out.println("克隆B: "+clonedPrototypeB);
    }

打印:

复制代码
原型A: ConcretePrototypeA{name='Prototype A'} hashcode= 1823541245
克隆A: ConcretePrototypeA{name='Prototype A'} hashcode= 1020154737
原型B: ConcretePrototypeB{value=42} hashcode= 398457879
克隆B: ConcretePrototypeB{value=42} hashcode= 1850954068

4. 应用场景


  • 对象的创建开销很大:通过克隆现有对象而不是重新创建,可以节省时间和资源。
  • 系统需要大量类似对象 :通过克隆原型对象,可以快速生成多个相似但独立的对象。
  • 对象的状态需要动态改变:通过克隆原型对象,可以创建具有特定状态的新对象。

情景回顾:

原型模式在实际应用中可能并不常见,或许你见到过但没留意,因为它的应用场景太少了,让我想起了在写一个多任务下载模块时,每下载一个文件其都有对应的mode,记录一些下载信息状态信息等内容,再进行更新进度的时候需要把这个对象发送出去,通知外界更新UI,有一个问题就是下载中操作的对象和发送出去的对象是同一个,就会出现异常现象,我发送出去的下载进度是90%,UI还没来得及更新,这边又将进度修改为95%了,emm... 可能我描述的问题,你觉的不严重,但这种不可预测的现象是我们不希望发生的。

其中解决方式一 就是克隆一个对象,让UI显示的和下载操作的对象互不干扰,这时如果你new一个新对象的话相比克隆就劣势就凸显出来了。

5. 优缺点


优点:

  • 提高对象创建效率:避免了复杂对象的重复创建,通过克隆现有对象来生成新对象。
  • 动态创建对象:可以在运行时动态创建对象,而无需了解具体的类。
  • 减少子类的数量:通过克隆原型对象,可以减少创建子类的数量,增强系统的灵活性。

缺点:

  • 深拷贝和浅拷贝问题:在涉及复杂对象时,深拷贝和浅拷贝的问题需要特别注意。如果对象包含对其他对象的引用,浅拷贝可能不够用,需要实现深拷贝。
  • 克隆方法的实现复杂:对于一些复杂的对象,克隆方法的实现可能比较复杂,需要处理对象间的依赖关系。

6. 深拷贝与浅拷贝


在原型模式中,克隆可以分为浅拷贝和深拷贝:

  • 浅拷贝:复制对象时,只复制对象本身,而不复制对象所引用的其他对象。也就是说,复制后的对象与原对象共享对其他对象的引用。
  • 深拷贝:复制对象时,不仅复制对象本身,还复制对象所引用的其他对象。这样,复制后的对象与原对象是完全独立的,不共享任何引用。

7. 深拷贝与浅拷贝示例


java 复制代码
// 原型接口
interface Prototype extends Cloneable {
    Prototype clone();
}

// 具体原型类
class ConcretePrototype implements Prototype {
    private String name;
    private List<String> list;

    public ConcretePrototype(String name) {
        this.name = name;
        this.list = new ArrayList<>();
    }

    public void addToList(String item) {
        list.add(item);
    }

    public List<String> getList() {
        return list;
    }

    @Override
    public Prototype clone() {
        try {
            ConcretePrototype copy = (ConcretePrototype) super.clone();
            // 深拷贝 -测试浅拷贝时注释下面代码!!!
            copy.list = new ArrayList<>(this.list);
            return copy;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String toString() {
        return "ConcretePrototype{name='" + name + "', list=" + list + "} list hashcode=" + list.hashCode();
    }
}

测试:

cpp 复制代码
    @Test
    public void test() {
        ConcretePrototype prototype = new ConcretePrototype("Prototype");
        prototype.addToList("Item1");
        prototype.addToList("Item2");

        // 浅拷贝示例
        ConcretePrototype shallowClone = (ConcretePrototype) prototype.clone();

        // 添加新项到原型对象的列表
        prototype.addToList("Item3");

        System.out.println("原型: " + prototype);
        System.out.println("浅拷贝: " + shallowClone);

        // 深拷贝示例
        ConcretePrototype deepClone = (ConcretePrototype) prototype.clone();

        // 添加新项到深拷贝对象的列表
        deepClone.addToList("Item4");

        System.out.println("原型: " + prototype);
        System.out.println("深拷贝: " + deepClone);
    }

测试浅拷贝打印:

复制代码
原型: ConcretePrototype{name='Prototype', list=[Item1, Item2, Item3]} list hashcode=1757018142
浅拷贝: ConcretePrototype{name='Prototype', list=[Item1, Item2, Item3]} list hashcode=1757018142

可以看出两个对象所引用的list对象为同一个

测试深拷贝打印:

复制代码
原型: ConcretePrototype{name='Prototype', list=[Item1, Item2, Item3]} list hashcode=1757018142
深拷贝: ConcretePrototype{name='Prototype', list=[Item1, Item2, Item3, Item4]} list hashcode=-1296039165

两个对象引用的list完全不一样了,操作互不影响

8. 设计模式的比较


原型模式与其他创建型设计模式(如工厂模式、抽象工厂模式、单例模式等)有其独特之处:

  • 与工厂模式的区别:工厂模式通过提供一个方法来创建对象,而原型模式通过复制现有对象来创建新的对象。工厂模式适合对象创建过程简单但需要解耦对象创建过程的场景,而原型模式适合对象创建过程复杂且需要高效创建对象的场景。
  • 与单例模式的区别:单例模式确保一个类只有一个实例,而原型模式则允许通过克隆来创建多个实例。它们解决的问题不同,前者关注的是实例的唯一性,后者关注的是高效创建对象。

9. 结论


原型模式是一种高效的对象创建模式,它通过克隆现有对象来创建新对象,避免了通过构造函数创建对象的高昂代价,尽管原型模式在许多方面具有优势,但在实现过程中需要注意对象间的引用关系,确保深拷贝和浅拷贝的正确实现,以避免不必要的资源浪费和潜在的错误。

相关推荐
晨米酱5 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机10 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机11 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机11 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机11 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤12 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴1 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤1 天前
工厂模式
设计模式