【设计模式】04-原型模式

原型模式简单来说就是自身拷贝的过程,分为浅拷贝和深拷贝。一般需要一个抽象接口Prototype有一个clone方法,实现类调用此方法就可以实现对象拷贝。这就可以使用Object的clone方法,只不过需要实现Cloneable接口并将clone覆盖为public的。

public abstract class Prototype<T> implements Cloneable,Serializable{
    public int prop1=1;
    public String prop2="2";
    @Override
    public T clone() throws CloneNotSupportedException {
        return (T)super.clone();
    }
}
public class ConcretePrototype1 extends Prototype<ConcretePrototype1> {

    @Override
    public String toString() {
        return "ConcretePrototype1{prop1=" + prop1 +", prop2=" + prop2 +'}';
    }
}

写个测试方法

private static void testClone() throws CloneNotSupportedException {
        ConcretePrototype1 p1=new ConcretePrototype1();
        ConcretePrototype1 c1=p1.clone();
        System.out.println("p1:"+p1);
        System.out.println("c1:"+c1);
        System.out.println("p1.prop2==c1.prop2 is "+(p1.prop2==c1.prop2));
    }

结果为:

p1:ConcretePrototype1{prop1=1, prop2=2}
c1:ConcretePrototype1{prop1=1, prop2=2}

p1.prop2==c1.prop2 is true

可以看到这种方式实现的拷贝对于对象属性只是复制了对象的引用,所以这种方式是浅拷贝。下面我们利用对象的序列化与反序列化实现对象的深拷贝。

public class ConcretePrototype2 extends Prototype<ConcretePrototype2> {

    @Override
    public ConcretePrototype2 clone() throws CloneNotSupportedException {
        ByteArrayOutputStream bytes=new ByteArrayOutputStream();
        try {
            ObjectOutputStream os=new ObjectOutputStream(bytes);
            os.writeObject(this);
            ByteArrayInputStream bais=new ByteArrayInputStream(bytes.toByteArray());
            ObjectInputStream is=new ObjectInputStream(bais);
            return (ConcretePrototype2)is.readObject();
        } catch (Exception e) {
            throw new CloneNotSupportedException(e.getMessage());
        }
    }
}

测试用例:

private static void testDeepClone() throws CloneNotSupportedException {
        ConcretePrototype2 p2=new ConcretePrototype2();
        ConcretePrototype2 c2=p2.clone();
        System.out.println("p2:"+p2);
        System.out.println("c2:"+c2);
        System.out.println("p2.prop2==cc.prop2 is "+(p2.prop2==c2.prop2));
    }

结果:

p2:com.pattern.prototype.ConcretePrototype2@355da254
c2:com.pattern.prototype.ConcretePrototype2@7291c18f
p2.prop2==cc.prop2 is false

原型模式主要适用于以下场景:
1、类初始化消耗资源较多。
2、new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
3、构造函数比较复杂。
4、循环体中生产大量对象时。

在Spring中, 原型模式应用得非常广泛。例如scope=prototype,在我们经常用的JSON.parseObject()也是一种原型模式。
 

原型模式的优缺点
优点:
1、性能优良, Java自带的原型模式是基于内存二进制流的拷贝, 比直接new一个对象性能上提升了许多。
2、可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点:
1、需要为每一个类配置一个克隆方法。
2、克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
3、在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深拷贝、浅拷贝需要运用得当。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值