首页 > 代码库 > (五)(创建型模式)原型模式

(五)(创建型模式)原型模式

一、原型模式(prototype pattern):

  使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。

二、应用场景:

  对象的创建非常复杂,可以使用原型模式快捷的创建对象。在运行过程中不知道对象的具体类型,可使用原型模式创建一个相同类型的对象,或者在运行过程中动态的获取到一个对象的状态。

三、应用实例:

  动物界的掌控者Tom,想要再建造一辆奥迪车,但是再去生产比较麻烦,有没有别的方法快速获取呢?

四、方案:

  UML图:

  技术分享

代码1:

package com.yq.test;

/**
 * Created by yq on 2016/11/23.
 */
public class Audi implements Cloneable {
    public Audi() {
        System.out.println("Audi构造ing...");
    }

    private String model = "奥迪";
    private String tire = "米其林";
    private String door = "单门";
    private Engine engine = new Engine("A6");

    @Override
    public Audi clone() {
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
        return (Audi) object;
    }

    @Override
    public String toString() {
        return "Audi{" +
                "model=‘" + model + ‘\‘‘ +
                ", tire=‘" + tire + ‘\‘‘ +
                ", door=‘" + door + ‘\‘‘ +
                ", engine=‘" + engine.toString() + ‘\‘‘ +
                ‘}‘;
    }
}

 可复制的原型类-奥迪车

package com.yq.test;

/**
 * Created by yq on 2016/11/23.
 */
public class Engine {
    public Engine(String str) {
        System.out.println(str + "引擎构造中ing...");
    }
}

原型类成员对象-引擎

package com.yq.test;

/**
 * Created by yq on 2016/11/23.
 */
public class client {
    public static void main(String[] args) {
        Audi audi = new Audi();
        System.out.println("实例对象 hashCode:" + audi.hashCode());
        System.out.println(audi.toString());
        Audi au = audi.clone();
        System.out.println("复制对象 hashCode:" + au.hashCode());
        System.out.println(au.toString());
    }
}
//output
A6引擎构造中ing...
Audi构造ing...
实例对象 hashCode:1956725890
Audi{model=‘奥迪‘, tire=‘米其林‘, door=‘单门‘, engine=‘com.yq.test.Engine@1540e19d‘}
复制对象 hashCode:1735600054
Audi{model=‘奥迪‘, tire=‘米其林‘, door=‘单门‘, engine=‘com.yq.test.Engine@1540e19d‘}

 客户端调用-复制奥迪车

分析:从代码1中输出可以看出,复制奥迪车时,没有构造引擎,也没有构造Audi,所以只是完整的复制了一个对象属性,对应的hashCode不等,说明是复制得到了一个新的对象。

    但是注意到原型对象和复制的新对象,他们的属性中引擎对象指向的是同一个引用,这当然不是我们想要的。

   这是因为对于clone方法,它执行的是浅拷贝,也就是说如果是引用类型的属性,则它不会进行拷贝,而是只拷贝引用。

 

代码2:

package com.yq.test;

/**
 * Created by yq on 2016/11/23.
 */
public class Audi implements Cloneable {
    private String model = "奥迪";
    private String tire = "米其林";
    private String door = "单门";
    private AudiEngine engine = new AudiEngine("A6");

    public Audi() {
        System.out.println("Audi构造ing...");
    }

    @Override
    public Audi clone() {
        Object object = null;
        try {
            object = super.clone();
            ((Audi)object).engine=engine.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
        return (Audi) object;
    }

    @Override
    public String toString() {
        return "Audi{" +
                "model=‘" + model + ‘\‘‘ +
                ", tire=‘" + tire + ‘\‘‘ +
                ", door=‘" + door + ‘\‘‘ +
                ", engine=‘" + engine.toString() + ‘\‘‘ +
                ‘}‘;
    }
}

 

  可复制的原型类-奥迪车

package com.yq.test;

/**
 * Created by yq on 2016/11/23.
 */
public class AudiEngine implements Cloneable {

    public AudiEngine(String str) {
        System.out.println(str + "引擎构造中ing...");
    }

    @Override
    public AudiEngine clone() {
        System.out.println("Engine clone() 调用ing...");
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
        return (AudiEngine) object;
    }
}

 

原型类成员对象-引擎

package com.yq.test;

/**
 * Created by yq on 2016/11/23.
 */
public class client {
    public static void main(String[] args) {
        Audi audi = new Audi();
        System.out.println("实例对象 hashCode:" + audi.hashCode());
        System.out.println(audi.toString());
        Audi au = audi.clone();
        System.out.println("复制对象 hashCode:" + au.hashCode());
        System.out.println(au.toString());
    }
}
//output
A6引擎构造中ing...
Audi构造ing...
实例对象 hashCode:1956725890
Audi{model=‘奥迪‘, tire=‘米其林‘, door=‘单门‘, engine=‘com.yq.test.AudiEngine@1540e19d‘}
Engine clone() 调用ing...
复制对象 hashCode:1735600054
Audi{model=‘奥迪‘, tire=‘米其林‘, door=‘单门‘, engine=‘com.yq.test.AudiEngine@14ae5a5‘}

 

客户端调用-复制奥迪车

分析:代码2实现了深拷贝,在Audi类的clone()方法中,指定了引用对象的拷贝,并在Engine类中也继承了cloneable,成功调用,从结果看出,Audi对象是新对象,新对象的Engine引用对象也是新对象,并且复制时都没有调用构造器。

 

备注:深拷贝,需要对指定实例的每个对象都指定拷贝,并且每个引用对象都要实现clone(),有比较大的代码量。

   原型模式是跨权限的,所以和单例模式冲突。

 

以上内容,纯属个人见解,如有错误,望不吝指正。

(五)(创建型模式)原型模式