Java设计模式(5)-原型设计模式

in 23种设计模式 with 1 comment

原型设计模式:

学习创建型模式最后一种-原型模式,该模式的思想是将一个对象作为原型,
对其进行复制、克隆,产生一个和原对象类似的新对象,以便使用

首先需要了解对象深、浅复制的概念:

· 浅拷贝:将一个对象复制后,基本数据类型的变量都会重新创建,
而引用类型,指向的还是原对象所指向的。

· 深拷贝:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。

简单来说,就是深拷贝进行了完全彻底的复制,而浅拷贝不彻底。

· Animal:具体原型类。实现克隆的具体操作。 

· Manager(这边用测试类代替):管理者类。让一个原型克隆自身,从而获得一个新的对象。

· 所有的Java类都继承至Object,而Object类提供了一个clone()方法,该方法可以
将一个java对象复制一份,因此在java中可以直接使用clone()方法来复制一个对象。
但是需要实现clone的Java类必须要实现一个接口:Cloneable.该接口表示该类能够复制
且具体复制的能力,如果不实现该接口而直接调用clone()方法会抛出
CloneNotSupportedException异常

Java中任何实现了Cloneable接口的类都可以通过调用clone()方法来复制一份自身然后传给调用者。一般而言,clone()方法满足:

· 对任何的对象x,都有x.clone() !=x,即克隆对象与原对象不是同一个对象。 

· 对任何的对象x,都有x.clone().getClass()==x.getClass(),即克隆对象与原对象的类型一样。 

· 如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
public class Animal implements Cloneable{

    private String name;
    private Integer age;

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

    public Animal(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
    //此处省略getter setter
}

测试:

public class CloneTest {
    
    public static void main(String[] args) {

        //创建
        Animal cat = new Animal("cat", 2);

        //克隆
        Animal cat_2 = (Animal) cat.clone();

        //cat
        System.out.println("cat:" + cat);
        //cat_2
        System.out.println("cat_2:" + cat_2);

        //同个对象?
        System.out.println( cat == cat_2);
        //x.clone().getClass()==x.getClass(),即克隆对象与原对象的类型一样
        System.out.println( cat.getClass() == cat_2.getClass());
    }
}

优缺点:

优点:
	· 如果创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,能够提高效率。
	
	· 可以使用深克隆保持对象的状态。
	
	· 原型模式提供了简化的创建结构。
缺点:
	· 在实现深克隆的时候可能需要比较复杂的代码。
	
	· 需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,
	这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事,
	必须修改其源代码,违背了“开闭原则”。

使用场景:

· 如果创建新对象成本较大,我们可以利用已有的对象进行复制来获得。

· 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占内存

不大的时候,也可以使用原型模式配合备忘录模式来应用。相反,如果对象的
状态变化很大,或者对象占用的内存很大,那么采用状态模式会比原型模式更好。 

· 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个
或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数
创建一个新实例更加方便。
0评论