Java设计模式(五)原型模式

一、原型模式介绍

原型模式是一种创建型设计模式,它允许我们通过克隆已有对象来创建新对象,而无需通过实例化来进行创建。

在原型模式中,我们定义一个原型接口或类,该接口或类声明了一个克隆方法。具体的原型类实现这个克隆方法,以便可以克隆自身。当客户端需要创建一个新对象时,它可以使用一个原型对象作为模板,并通过克隆方法来克隆这个原型对象,从而创建一个新对象。

二、原型模式代码示例

下面是一个原型模式的示例代码:

//1.原型接口
public interface Prototype {
    Prototype clone();
}
//2.具体原型类
public class ConcretePrototype implements Prototype {
    private int value;

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

    public int getValue() {
        return value;
    }

    @Override
    public Prototype clone() {
        return new ConcretePrototype(value);
    }
}
//3.测试方法
    public static void main(String[] args) {
        ConcretePrototype prototype = new ConcretePrototype(10);
        ConcretePrototype clone = (ConcretePrototype) prototype.clone();
        System.out.println("prototype value: " + prototype.getValue());
        System.out.println("clone value: " + clone.getValue());
    }

在上面的代码中,Prototype是原型接口,它定义了一个克隆方法。ConcretePrototype是具体原型类,它实现了Prototype接口,并为克隆方法提供了具体的实现。在测试代码中,我们创建了一个ConcretePrototype对象,并使用克隆方法来创建了一个新对象。我们还可以通过修改原型对象来影响克隆对象的属性值。

原型模式可以很好地解决某些场景下的对象创建问题,特别是在创建对象的过程比较复杂或者耗时的情况下。原型模式可以大大简化对象创建的过程,提高代码复用性和可维护性。但是,需要注意的是,在使用原型模式时,克隆出来的新对象可能与原始对象存在一定的关联性,需要在使用时进行特殊处理。

三、深克隆和浅克隆(深复制和浅复制)

在 Java 中,对象的复制分为两种类型:深复制和浅复制。它们的区别在于复制后新对象与原始对象之间的关联性。

浅复制是指复制一个对象,新对象与原始对象共享同一个引用类型的数据成员(如数组、集合、对象等),因此对于这些共享的数据成员的修改会影响到所有引用它们的对象,包括原始对象和复制对象。

深复制则是指复制一个对象,新对象与原始对象不共享任何引用类型的数据成员,即它们之间的数据成员完全独立。因此对于新对象的修改不会影响到原始对象。

在 Java 中,通过实现 Cloneable 接口和重写 Object 类中的 clone() 方法来实现对象的复制。对于浅复制,直接调用 Object 类的 clone() 方法即可;对于深复制,需要在 clone() 方法中对引用类型的数据成员进行递归复制。

下面是一个使用浅复制和深复制的示例代码:

//定义一个包含引用类型数据成员的类
public class Person implements Cloneable {
    private String name;
    private List<String> hobbies;

    public Person(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }

    public String getName() {
        return name;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    // 浅复制
    public Person shallowCopy() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

    // 深复制
    public Person deepCopy() throws CloneNotSupportedException {
        Person clone = (Person) super.clone();
        clone.hobbies = new ArrayList<>(this.hobbies);
        return clone;
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        // 创建一个原始对象
        List<String> hobbies = new ArrayList<>();
        hobbies.add("reading");
        hobbies.add("swimming");
        Person original = new Person("Tom", hobbies);

        // 浅复制一个新对象
        Person shallowCopy = original.shallowCopy();
        System.out.println("shallowCopy: " + shallowCopy.getName() + ", " + shallowCopy.getHobbies());
        shallowCopy.getHobbies().add("travel");
        System.out.println("original: " + original.getName() + ", " + original.getHobbies());

        // 深复制一个新对象
        Person deepCopy = original.deepCopy();
        System.out.println("deepCopy: " + deepCopy.getName() + ", " + deepCopy.getHobbies());
        deepCopy.getHobbies().add("coding");
        System.out.println("original: " + original.getName() + ", " + original.getHobbies());
    }
}

输出结果:
shallowCopy: Tom, [reading, swimming]
original: Tom, [reading, swimming, travel]
deepCopy: Tom, [reading, swimming, travel]
original: Tom, [reading, swimming, travel]

在上面的代码中,Person是一个包含引用类型数据成员的类,它实现了 Cloneable 接口并重写了 clone() 方法。在客户端代码中,我们先创建一个原始对象original,然后分别进行浅复制和深复制。对于浅复制,我们直接调用了super.clone()方法,之后我们修改浅复制的新对象shallowCopyhobbies列表,添加了一个新的爱好"travel",并打印出原始对象originalhobbies列表,可以看到新添加的爱好也被修改了。这是因为浅复制的新对象和原始对象共享同一个hobbies列表,它们只是拥有了同一个引用而已。

接着,我们对深复制的新对象deepCopy也添加了一个新的爱好"coding",再次打印出原始对象originalhobbies列表,发现它并没有受到影响。这是因为深复制的新对象拥有了一个全新的hobbies列表,它与原始对象的列表是完全独立的。

因此,浅复制和深复制的区别在于新对象与原始对象之间是否共享引用类型的数据成员。对于需要独立修改的数据成员,应该使用深复制,否则可能会影响到其他对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Dantesding

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

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

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

打赏作者

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

抵扣说明:

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

余额充值