客户端如果需要使用一个类的实例时通常是使用这个类的构造方法以及setter 方法去构建这个类的实例。但是在某些情形下,可能不允许直接调用构造方法或者是为了解决Java 的值引用问题。 在设计模式中 建造者模式、工厂方法、抽象工厂都可以避免客户端直接调用构造方法。同样原型模式也可以解决这个问题。
首先需要知道在JAVA 中所有的引用都是值引用。
/**
*
* @author zhangwei
* @version $Id: TestModel.java, v 0.1 2014年9月23日 上午9:24:41 zhangwei Exp $
*/
public class TestModel {
//值
String value;
/**
* Getter method for property <tt>value</tt>.
*
* @return property value of value
*/
public String getValue() {
return value;
}
/**
* Setter method for property <tt>value</tt>.
*
* @param value value to be assigned to property value
*/
public void setValue(String value) {
this.value = value;
}
}
/**
*
* @author Lenovo
* @version $Id: ValueReferenceClient.java, v 0.1 2014年9月23日 上午9:22:20 Lenovo Exp $
*/
public class ValueReferenceClient {
/**
*
* @param args
*/
public static void main(String[] args) {
TestModel u = new TestModel();
u.setValue("123");
TestModel m = u;
u.setValue("456");
System.out.println(MessageFormat.format("m.value={0}|u.value={1} ", m.getValue(),
u.getValue()));
}
}
结果是:m.value=456|u.value=456
上述就是由于值引用导致的问题,有的时候需要并不是这个对象的引用而是这个对象的副本。此时原型模式就可以凸显作用了。
/**
*
* @author Lenovo
* @version $Id: UserModel.java, v 0.1 2014年9月23日 上午9:03:51 Lenovo Exp $
*/
public class UserModel implements Cloneable {
private String userId;
private String bindMobile;
private String contact;
private String address;
private String certNo;
/**
* Getter method for property <tt>userId</tt>.
*
* @return property value of userId
*/
public String getUserId() {
return userId;
}
/**
* Setter method for property <tt>userId</tt>.
*
* @param userId value to be assigned to property userId
*/
public void setUserId(String userId) {
this.userId = userId;
}
/**
* Getter method for property <tt>bindMobile</tt>.
*
* @return property value of bindMobile
*/
public String getBindMobile() {
return bindMobile;
}
/**
* Setter method for property <tt>bindMobile</tt>.
*
* @param bindMobile value to be assigned to property bindMobile
*/
public void setBindMobile(String bindMobile) {
this.bindMobile = bindMobile;
}
/**
* Getter method for property <tt>contact</tt>.
*
* @return property value of contact
*/
public String getContact() {
return contact;
}
/**
* Setter method for property <tt>contact</tt>.
*
* @param contact value to be assigned to property contact
*/
public void setContact(String contact) {
this.contact = contact;
}
/**
* Getter method for property <tt>address</tt>.
*
* @return property value of address
*/
public String getAddress() {
return address;
}
/**
* Setter method for property <tt>address</tt>.
*
* @param address value to be assigned to property address
*/
public void setAddress(String address) {
this.address = address;
}
/**
* Getter method for property <tt>certNo</tt>.
*
* @return property value of certNo
*/
public String getCertNo() {
return certNo;
}
/**
* Setter method for property <tt>certNo</tt>.
*
* @param certNo value to be assigned to property certNo
*/
public void setCertNo(String certNo) {
this.certNo = certNo;
}
/**
* @see java.lang.Object#clone()
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "UserModel [userId=" + userId + ", bindMobile=" + bindMobile + ", contact="
+ contact + ", address=" + address + ", certNo=" + certNo + "]";
}
}
/**
*
* @author Lenovo
* @version $Id: Client.java, v 0.1 2014年9月23日 上午9:06:15 Lenovo Exp $
*/
public class Client {
/**
*
* @param args
* @throws CloneNotSupportedException
*/
public static void main(String[] args) throws CloneNotSupportedException {
UserModel source = new UserModel();
source.setAddress("杭州西湖区万塘路18号黄龙时代广场");
source.setUserId("2088123456123456");
source.setBindMobile("13916309243");
source.setCertNo("32132019900912");
source.setContact("13916309243");
UserModel dest = (UserModel) source.clone();
System.out.println(dest == source);
}
}
结果是:false
这种是借助Object.clone()方法实现原型模式,但是该方法也是有一定的局限性,如果对象的属性是一个数组或者其他对象则没有办法对其进行clone.
此时可以使用序列化的方式进行克隆
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T object) {
T cloneObject = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
cloneObject = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObject;
}