您的位置:首页 > 其它

原型模式

2013-04-08 14:44 441 查看
一)故事

个性化电子账单

二)定义

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

三)代码例子

共计一个类:1)原型类;

1)原型类
/**
*  原型类
*
* @author levovo
*/
public class PrototypeClass implements java.lang.Cloneable {
private String title = null;// 完全拷贝(深拷贝)
private String name = null;// 完全拷贝(深拷贝)
private int number = 0; // 完全拷贝(深拷贝)
// 数组与对象
private ArrayList<String> list = new ArrayList(); // 引用拷贝(浅拷贝)
private Version version = new Version();// 引用拷贝(浅拷贝)
private Integer[] integerArray = new Integer[6];// 引用拷贝(浅拷贝)
private int arrayIndex = 0;
// static
private static Version versionStatic = new Version(); // 引用拷贝(浅拷贝)(仅有一个实例)
private static int numberStatic = 0;// 引用拷贝(浅拷贝)(仅有一个实例)
// final
private final Version versionFinal = new Version();
private final int numberFinal = 999;
// 覆盖父类Object方法
@Override
protected PrototypeClass clone() {
PrototypeClass prototype = null;
try {
// 浅拷贝
prototype = (PrototypeClass)super.clone();
// 对象深拷贝
prototype.list = (ArrayList<String>)this.list.clone();
// 对象深拷贝
prototype.version = (Version)this.version.clone();
// 数组深拷贝
prototype.integerArray = (Integer[])this.integerArray.clone();
} catch (CloneNotSupportedException ex) {

}
return prototype;
}

public void setTitle(String _title) {
this.title = _title;
//        System.out.println("PrototypeClass()->setTitle():"+this.title);
}

public String getTitle() {
return this.title;
}

/**
* @return the number
*/
public int getNumber() {
return number;
}

/**
* @param number the number to set
*/
public void setNumber(int number) {
this.number = number;
}

public void setList(String value) {
this.getList().add(value);
}

public ArrayList<String> getList() {
return this.list;
}

/**
* @return the name
*/
public String getName() {

4000
return name;
}

/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}

/**
* @param list the list to set
*/
public void setList(ArrayList<String> list) {
this.list = list;
}

/**
* @return the version
*/
public Version getVersion() {
return version;
}

/**
* @param version the version to set
*/
public void setVersion(Version version) {
this.version = version;
}

/**
* @return the integerArray
*/
public Integer[] getIntegerArray() {
return integerArray;
}

/**
* @param integerArray the integerArray to set
*/
public void setIntegerArray(int integerArray) {
this.integerArray[arrayIndex] = integerArray;
}

/**
* @return the versionFinal
*/
public Version getVersionFinal() {
return versionFinal;
}

/**
* @return the numberFinal
*/
public int getNumberFinal() {
return numberFinal;
}

/**
* @return the versionStatic
*/
public static Version getVersionStatic() {
return versionStatic;
}

/**
* @param aVersionStatic the versionStatic to set
*/
public static void setVersionStatic(Version aVersionStatic) {
versionStatic = aVersionStatic;
}

/**
* @return the numberStatic
*/
public static int getNumberStatic() {
return numberStatic;
}

/**
* @param aNumberStatic the numberStatic to set
*/
public static void setNumberStatic(int aNumberStatic) {
numberStatic = aNumberStatic;
}
}


一个类
/**
*  一个类
*
* @author levovo
*/
public class Version implements java.lang.Cloneable {
private String name = null;
private int code = 0;

// 覆盖父类Object方法
@Override
protected Version clone() {
Version version = null;
try {
version = (Version)super.clone();
} catch (CloneNotSupportedException ex) {

}
return version;
}

/**
* @return the name
*/
public String getName() {
return name;
}

/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}

/**
* @return the code
*/
public int getCode() {
return code;
}

/**
* @param code the code to set
*/
public void setCode(int code) {
this.code = code;
}

}


场景使用例子

/**
*  场景使用例子
*
* @author levovo
*/
public class Client {
public static void main(String[] args) {
// 旧的
PrototypeClass prototypeOld = new PrototypeClass();
prototypeOld.setTitle("titleOld");
String name = new String("nameOld");
prototypeOld.setName(name);
prototypeOld.setNumber(10001);
prototypeOld.setList("listOld");
prototypeOld.getVersion().setName("version name....Old");
prototypeOld.getVersion().setCode(20001);
prototypeOld.setIntegerArray(100);
prototypeOld.setNumberStatic(100);
prototypeOld.getVersionStatic().setName("version name...static...Old");
prototypeOld.getVersionStatic().setCode(30001);
//        prototypeOld.set
// clone的
PrototypeClass prototypeClone = prototypeOld.clone();
// 修改
System.out.println("--- modify ---");
prototypeOld.setTitle("titleChange");
String name1 = new String("nameChange");
prototypeOld.setName(name1);
prototypeOld.setNumber(10002);
prototypeOld.setList("listChange");
prototypeOld.getVersion().setName("version name....Change");
prototypeOld.getVersion().setCode(20002);
prototypeOld.setIntegerArray(200);
prototypeOld.setNumberStatic(200);
prototypeOld.getVersionStatic().setName("version name...static...Change");
prototypeOld.getVersionStatic().setCode(30002);
System.out.println("--- 比较 ---");
//        prototypeOld.getTitle().contains(name);
if (prototypeOld.getTitle().equals(prototypeClone.getTitle())) {
System.out.println("String title -> 属于引用拷贝(浅拷贝)");
}else{
System.out.println("String title -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getName().equals(prototypeClone.getName())) {
System.out.println("String name -> 属于引用拷贝(浅拷贝)");
}else{
System.out.println("String name -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getNumber() == prototypeClone.getNumber()) {
System.out.println("int number -> 属于引用拷贝(浅拷贝)");
}else{
System.out.println("int number -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getList().equals(prototypeClone.getList())) {
System.out.println("ArrayList<String> list -> 属于引用拷贝(浅拷贝)");
}else{
System.out.println("ArrayList<String> list -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getVersion().equals(prototypeClone.getVersion())) {
System.out.println("Version version -> 属于引用拷贝(浅拷贝)");
}else{
System.out.println("Version version -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getVersion().getName().equals(prototypeClone.getVersion().getName())) {
System.out.println("Version version.getName() -> 属于引用拷贝(浅拷贝)");
}else{
System.out.println("Version version.getName() -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getVersion().getCode() == prototypeClone.getVersion().getCode()) {
System.out.println("Version version.getCode() -> 属于引用拷贝(浅拷贝)");
}else{
System.out.println("Version version.getCode() -> 属于完全拷贝(深拷贝)");
}

System.out.println("prototypeOld.getIntegerArray()[0]:"+prototypeOld.getIntegerArray()[0]);
System.out.println("prototypeClone.getIntegerArray()[0]:"+prototypeClone.getIntegerArray()[0]);
if (prototypeOld.getIntegerArray()[0] == prototypeClone.getIntegerArray()[0]) {
System.out.println("Integer[] integerArray -> 属于引用拷贝(浅拷贝)");
}else{
System.out.println("Integer[] integerArray -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getNumberStatic() == prototypeClone.getNumberStatic()) {
System.out.println("static int numberStatic -> 属于引用拷贝(浅拷贝)(仅一个实例)");
}else{
System.out.println("static int numberStatic -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getVersionStatic().equals(prototypeClone.getVersionStatic())) {
System.out.println("static Version versionStatic -> 属于引用拷贝(浅拷贝)(仅一个实例)");
}else{
System.out.println("static Version versionStatic -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getVersionStatic().getName().equals(prototypeClone.getVersionStatic().getName())) {
System.out.println("static Version versionStatic.getName() -> 属于引用拷贝(浅拷贝)(仅一个实例)");
}else{
System.out.println("static Version versionStatic.getName() -> 属于完全拷贝(深拷贝)");
}

if (prototypeOld.getVersionStatic().getCode() == prototypeClone.getVersionStatic().getCode()) {
System.out.println("static Version versionStatic.getCode() -> 属于引用拷贝(浅拷贝)(仅一个实例)");
}else{
System.out.println("static Version versionStatic.getCode() -> 属于完全拷贝(深拷贝)");
}

System.out.println("prototypeOld.getNumberFinal():"+prototypeOld.getNumberFinal());
System.out.println("prototypeClone.getNumberFinal():"+prototypeClone.getNumberFinal());

// 总论:
// 1)内部的数组(如Object[]和ArrayList<String>)和对象是拷贝引用,不是拷贝对象
// 2)基本类型是属于完全拷贝(深拷贝),String也算是基本类型
}
}

打印结果:

--- modify ---
--- 比较 ---
String title -> 属于完全拷贝(深拷贝)
String name -> 属于完全拷贝(深拷贝)
int number -> 属于完全拷贝(深拷贝)
ArrayList<String> list -> 属于完全拷贝(深拷贝)
Version version -> 属于完全拷贝(深拷贝)
Version version.getName() -> 属于完全拷贝(深拷贝)
Version version.getCode() -> 属于完全拷贝(深拷贝)
prototypeOld.getIntegerArray()[0]:200
prototypeClone.getIntegerArray()[0]:100
Integer[] integerArray -> 属于完全拷贝(深拷贝)
static int numberStatic -> 属于引用拷贝(浅拷贝)(仅一个实例)
static Version versionStatic -> 属于引用拷贝(浅拷贝)(仅一个实例)
static Version versionStatic.getName() -> 属于引用拷贝(浅拷贝)(仅一个实例)
static Version versionStatic.getCode() -> 属于引用拷贝(浅拷贝)(仅一个实例)
prototypeOld.getNumberFinal():999
prototypeClone.getNumberFinal():999


四)优点

1)性能优良

原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。

2)逃避构造函数的约束

这即是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。

五)缺点

六)使用场景

1)资源优化场景

类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。

2)性能和安全要求的场景

通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

3)一个对象多个修改者的场景

一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。

原型模式已经与Java融为一体了,随时拿来用,java.lang.Cloneable

七)注意事项

1)构造函数不会被执行

2)浅拷贝和深拷贝

浅拷贝,即拷贝引用,指向原生对象的内部元素地址,共享一个私有变量。

深拷贝,即完全拷贝,两个对象这间没有任何的瓜葛,你修改你的,我修改我的,不相互影响。

注:深拷贝和浅拷贝建议不要混合使用,特别是在涉及类的继承时,父类有多个引用的情况就非常复杂,建议的方案是深拷贝和浅拷贝分开实现。

3)clone与final两个冤家

对象clone与对象内的final关键字是有冲突的,想要实现拷贝,则删除掉final关键字,这是最便捷、安全、快捷的方式。你要使用clone方法,在类的成员变量上就不要增加final关键字。

注:要使用clone方法,类的成员变量上就不要增加final关键字。

八)扩展

九)总结

理解浅拷贝和深拷贝,浅拷贝是引用,浅拷贝是完全拷贝。基本类型,如:int,long,double和String对象(String对象看作是基本类型)都是深拷贝,而数组(如:Integer[]、Double[])和对象(如:ArrayList<String>、Version())都是浅拷贝。想要实现数组和对象的深拷贝,则在clone()方法里加入深拷贝代码,如下:

// 实现java.lang.Cloneable接口中的方法clone()

public class PrototypeClass implements java.lang.Cloneable {

    // 数组与对象

    private ArrayList<String> list = new ArrayList(); // 引用拷贝(浅拷贝)

    private Version version = new Version();// 引用拷贝(浅拷贝)

    private Integer[] integerArray = new Integer[6];// 引用拷贝(浅拷贝)

    private int arrayIndex = 0;

    // 覆盖父类Object方法

    @Override

    protected PrototypeClass clone() {

        PrototypeClass prototype = null;

        try {

            // 浅拷贝

            prototype = (PrototypeClass)super.clone();

            // 对象深拷贝

            prototype.list = (ArrayList<String>)this.list.clone();

            // 对象深拷贝

            prototype.version = (Version)this.version.clone();

            // 数组深拷贝

            prototype.integerArray = (Integer[])this.integerArray.clone();

        } catch (CloneNotSupportedException ex) {

            

        }

        return prototype;

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息