最近开始看设计模式,这几天看了按照设计模式应用场景划分的创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
这五种设计模式中。其中工厂方法模式、抽象工厂模式以及单例模式在平常开发以及阅读开源代码的时候已经写过或者看过应用的代码,所以看起来也相对轻松点。
单例模式现在比较常用的首先方式是使用内部类维护单例的创建以及初始化,JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的,这样在第一次get实例的时候,JVM能够给确定这个实例会且只会被创建一次,并且保证会初始化完毕,而且也只是在第一次get的时候会使用互斥机制,而后每次调用都直接使用已经创建并且初始化好的实例,当然对于在内部类中创建并且初始化实例的时候可能出现的异常情况需要充分考虑并且依据实际应用做相应处理。
建造者模式,这个有点类似与组合,在实际开发中很多情况下其实已经使用了,例如复杂业务需要的数据模型。
原型模式,该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。主要设计到的两个概念是深复制与浅复制,以下分别列举一个例子:
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
浅复制:
private static final long serialVersionUID = 1L;
private Test test;
private int i;
/**
* 浅复制
*/
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
public Test getTest() {
return test;
}
public void setTest(Test test) {
this.test = test;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public static void main(String[] args) throws CloneNotSupportedException {
Prototype prototype = new Prototype();
Test test = new Test();
test.setString("test for clone");
test.setValue(100);
prototype.setTest(test);
Prototype prototypeClone = (Prototype) prototype.clone();
System.out.println(prototypeClone.getClass() == prototype.getClass());
System.out.println(prototype.getClass());
System.out.println(prototypeClone.getClass());
System.out.println(prototypeClone);
System.out.println(prototypeClone.equals(prototype));
System.out.println(prototypeClone != prototype);
prototype.setI(10);
System.out.println("prototype i : " + prototype.getI());
System.out.println("prototypeClone i : " + prototypeClone.getI());
System.out.println("prototype test value : " + prototype.getTest().getValue());
System.out.println("prototype test string : " + prototype.getTest().getString());
System.out.println("prototypeClone test value : " + prototypeClone.getTest().getValue());
System.out.println("prototypeClone test string : " + prototypeClone.getTest().getString());
prototypeClone.setI(18);
prototypeClone.getTest().setString("clone change");
System.out.println("prototype i : " + prototype.getI());
System.out.println("prototypeClone i : " + prototypeClone.getI());
System.out.println("prototype test value : " + prototype.getTest().getValue());
System.out.println("prototype test string : " + prototype.getTest().getString());
System.out.println("prototypeClone test value : " + prototypeClone.getTest().getValue());
System.out.println("prototypeClone test string : " + prototypeClone.getTest().getString());
}
}
class Test {
private int value;
private String string;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}
深复制:
public static void main(String[] args) throws CloneNotSupportedException {
DeepTest deepTest = new DeepTest();
deepTest.setString("deepTest deep clone");
deepTest.setValue(100);
Nest nest = new Nest();
nest.setDeepTest(deepTest);
nest.setNestName("nest");
Nest nestClone = (Nest) nest.clone();
System.out.println(nest.getClass() == nestClone.getClass());
System.out.println(nest.equals(nestClone));
System.out.println("nest string : " + nest.getNestName());
System.out.println("nest deepTest : " + nest.getDeepTest());
System.out.println("nest deepTest string : " + nest.getDeepTest().getString());
System.out.println("nest deepTest value : " + nest.getDeepTest().getValue());
System.out.println("nest clone string : " + nestClone.getNestName());
System.out.println("nest clone deepTest : " + nestClone.getDeepTest());
System.out.println("nest clone deepTest string : " + nestClone.getDeepTest().getString());
System.out.println("nest clone deepTest value : " + nestClone.getDeepTest().getValue());
nestClone.setNestName("nestClone");
nestClone.getDeepTest().setString("nestClone deep clone");
nestClone.getDeepTest().setValue(101);
System.out.println(" test change --------------------");
System.out.println("nest string : " + nest.getNestName());
System.out.println("nest deepTest : " + nest.getDeepTest());
System.out.println("nest deepTest string : " + nest.getDeepTest().getString());
System.out.println("nest deepTest value : " + nest.getDeepTest().getValue());
System.out.println("nest clone string : " + nestClone.getNestName());
System.out.println("nest clone deepTest : " + nestClone.getDeepTest());
System.out.println("nest clone deepTest string : " + nestClone.getDeepTest().getString());
System.out.println("nest clone deepTest value : " + nestClone.getDeepTest().getValue());
}
}
class DeepTest implements Cloneable {
@Override
public Object clone() throws CloneNotSupportedException {
DeepTest deepTest = (DeepTest) super.clone();
return deepTest;
}
private int value;
private String string;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}
class Nest implements Cloneable {
@Override
public Object clone() throws CloneNotSupportedException {
Nest nest = (Nest) super.clone();
nest.setDeepTest((DeepTest) nest.getDeepTest().clone());
return nest;
}
private DeepTest deepTest;
private String nestName;
public DeepTest getDeepTest() {
return deepTest;
}
public void setDeepTest(DeepTest deepTest) {
this.deepTest = deepTest;
}
public String getNestName() {
return nestName;
}
public void setNestName(String nestName) {
this.nestName = nestName;
}
}
其实这里实现的深复制就是多引用类型进行递进的浅复制,最终肯定是最深一层是基本类型,String对象是一个例外,它clone后的表现好象也实现了深度clone,虽然这只是一个假象。然后逐步变相实现深复制。还有一种方式是使用序列化来做深复制,这个感兴趣的可以自己试试。