@linux1s1s
2019-02-18T19:27:53.000000Z
字数 3180
阅读 1510
Base
2017-01
在阎宏博士的《JAVA与模式》一书中开头是这样描述原型(Prototype)模式的:
原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。这就是选型模式的用意。
为了表达清楚上面枯燥的表达,我们用UML类图来说明一下:
接下来看看源码:
public interface Contract {
Contract clone();
String getName();
void setName(String name);
}
public class PrototypeA implements Contract {
private String name;
@Override
public Contract clone() {
PrototypeA a = new PrototypeA();
a.setName(name);
return a;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return "PrototypeA " + "[hashcode=" + hashCode() + "] " + "[name=" + name + "]";
}
@Override
public void setName(String name) {
this.name = name;
}
}
public class PrototypeB implements Contract {
private String name;
@Override
public Contract clone() {
PrototypeB b = new PrototypeB();
b.setName(name);
return b;
}
@Override
public String toString() {
return "PrototypeB " + "[hashcode=" + hashCode() + "] " + "[name=" + name + "]";
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}
public class PrototypeManager {
private static PrototypeManager INSTANCE;
private final Map<String, Contract> mContracts;
private PrototypeManager() {
mContracts = new HashMap<String, Contract>();
}
public static PrototypeManager getInstance() {
if (INSTANCE == null) {
synchronized (PrototypeManager.class) {
if (INSTANCE == null) {
INSTANCE = new PrototypeManager();
}
}
}
return INSTANCE;
}
public boolean put(String id, Contract c) {
if (TextUtils.isEmpty(id) || c == null) {
return false;
}
if (mContracts.containsKey(id)) {
return false;
}
mContracts.put(id, c);
return true;
}
public Contract get(String id) {
if (TextUtils.isEmpty(id)) {
return null;
}
return mContracts.get(id);
}
public boolean remove(String id) {
if (TextUtils.isEmpty(id)) {
return false;
}
if (!mContracts.containsKey(id)) {
return true;
}
mContracts.remove(id);
return true;
}
}
public class TestCase {
public static void exe() {
try {
Contract c1 = new PrototypeA();
PrototypeManager.getInstance().put("p1", c1);
// 获取原型来创建对象
Contract c3 = PrototypeManager.getInstance().get("p1").clone();
c3.setName("susan");
Log.i("Prototype", "第一个实例:" + c3);
// 有人动态的切换了实现
Contract c2 = new PrototypeB();
PrototypeManager.getInstance().put("p1", c2);
// 重新获取原型来创建对象
Contract c4 = PrototypeManager.getInstance().get("p1").clone();
c4.setName("bili");
Log.i("Prototype", "第二个实例:" + c4);
// 有人注销了这个原型
PrototypeManager.getInstance().remove("p1");
// 再次获取原型来创建对象
Contract c5 = PrototypeManager.getInstance().get("p1").clone();
c5.setName("coqi");
Log.i("Prototype", "第三个实例:" + c5);
} catch (NullPointerException e) {
// TODO: handle exception
}
}
}
01-11 06:17:03.053 13654-13654/? I/Prototype: 第一个实例:PrototypeA [hashcode=1384349684] [name=susan]
01-11 06:17:03.057 13654-13654/? I/Prototype: 第二个实例:PrototypeA [hashcode=1384350260] [name=bili]
public Object deepClone() throws IOException, ClassNotFoundException{
//将对象写到流里
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//从流里读回来
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
原型模式要求对象实现一个可以“克隆”自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例。这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建。
参考博文:
《JAVA与模式》之原型模式