跟着《软件秘笈---设计模式那点事》学习
预热:JAVA深复制(深克隆)与浅复制(浅克隆)
1.浅复制与深复制概念
⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原对象。
2.Java的clone()方法
(1)clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
④如果自己创建,那必须是先cloneable接口。
(2)Java中对象的克隆
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
②在派生类中覆盖基类的clone()方法,并声明为public。
③在派生类的clone()方法中,调用super.clone()。
④在派生类中实现Cloneable接口。
定义:
原型模式(Prototype Pattren),用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
角色:
(1)原型类
(2)生产原型的工厂(抽象)
(3)原型工厂实现类
(4)客户端
类图:
实例:
pojo类
package com.prototype.pojo;
public class DayLife implements Cloneable {
// 起床
private String getUp;
// 坐公交
private String byBus;
// 下车,买早餐
private String getFood;
// 中午小憩
private String noon;
// 下午开始工作
private String afternoonWork;
// 下班回家
private String goHome;
// 晚上休闲
private String night;
public String getGetUp() {
return getUp;
}
public void setGetUp(String getUp) {
this.getUp = getUp;
}
public String getByBus() {
return byBus;
}
public void setByBus(String byBus) {
this.byBus = byBus;
}
public String getGetFood() {
return getFood;
}
public void setGetFood(String getFood) {
this.getFood = getFood;
}
public String getNoon() {
return noon;
}
public void setNoon(String noon) {
this.noon = noon;
}
public String getAfternoonWork() {
return afternoonWork;
}
public void setAfternoonWork(String afternoonWork) {
this.afternoonWork = afternoonWork;
}
public String getGoHome() {
return goHome;
}
public void setGoHome(String goHome) {
this.goHome = goHome;
}
public String getNight() {
return night;
}
public void setNight(String night) {
this.night = night;
}
public void print() {
System.out.println(this.getGetUp());
System.out.println(this.getByBus());
System.out.println(this.getGetFood());
System.out.println(this.getNoon());
System.out.println(this.getAfternoonWork());
System.out.println(this.getGoHome());
System.out.println(this.getNight());
}
@Override
public DayLife clone(){
try {
return (DayLife)super.clone();//这是Object的方法
} catch (Exception e) {
}
return null;
}
}
抽闲原型工厂
public interface ILifeFactory {
public DayLife getNewIntance();
}
public class LifeFactoryImpl implements ILifeFactory {
//DayLife对象实例用于初始化
private static DayLife dayLife = null;
@Override
public DayLife getNewIntance() {
if(dayLife == null){
System.out.println("----New DayLife----");
dayLife = new DayLife();
dayLife.setGetUp("7:00起床");
dayLife.setByBus("7:30坐公交");
dayLife.setGetFood("8:30到公司");
dayLife.setNoon("11:45吃午饭,吃完小憩");
dayLife.setAfternoonWork("13:30开始下午的工作");
dayLife.setGoHome("17:45准时下班");
dayLife.setNight("晚上休闲娱乐");
}else{
System.out.println("+++Clone DayLife++++");
dayLife = dayLife.clone();
}
return dayLife;
}
}
客户端
public class Client {
public static void main(String[] args) {
//创建工厂
ILifeFactory lifeFactory = new LifeFactoryImpl();
//打印输出DayLife默认内容
lifeFactory.getNewIntance().print();
//再次获得DayLife,修改getUp内容后,输出内容
System.out.println("------------------------------------------------------------");
DayLife dayLife = lifeFactory.getNewIntance();
dayLife.setGetUp("早上懒床了,7:15才起床!!!!");
dayLife.print();
//再次获得DayLife,修改getUp内容后,输出内容
System.out.println("------------------------------------------------------------");
DayLife dayLife2 = lifeFactory.getNewIntance();
dayLife2.setGetUp("早上懒床了,7:30才起床!!!!");
dayLife2.print();
}
}
分析:
原型方法的核心是clone方法,通过这个方法进行对象的复制,
1:克隆对象时对象的构造方法不执行
2:深复制和浅复制
上面这个例子的核心是clone方法,而clone方法是浅复制。如果要深复制,那需要把持有的对象也clone,上面引子里说的很清楚,这里不赘述了。
使用场合:
(1)产生对象过程比较复杂,初始化需要很多资源时。
(2)希望框架原型和产生对象分开时。
(3)同一个对象可能会供其他调用者同事访问时。
一句话总结:
通过Object的Clone方法,创建对象。
Java SDK中的原型模式
实现Cloneable接口
参考资料:
《软件秘笈---设计模式那点事》
http://www.cnblogs.com/yxnchinahlj/archive/2010/09/20/1831615.html