在编程中有时候我们会发现,当我们需要一个实例,可是这个实例的创建过程十分复杂,在执行过程中
会消耗大量的时间,同时创建第一个实例和创建第二个时间的初始化信息并未改变。在此种情况下,直接New
一个实例对象显得太浪费,不合理。
那么如何避免使用new一个实例的方法,提升程序的性能呢?可以通过原型模式改善!
原型模式:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。他允许一个对象创建另一
个可定制的对象,却不关心创建的细节。其工作原理是:通过将一个原型对象传给那个要发动创建的对
象,这个要发动的对象通过请求原型对象拷贝自己来实现创建。
其实说白了原型设计模式就是对对象的复制,说的更直白一些也就是对数据的复制。但是在对数据
进行复制的时候有两个问题是我们必须考虑到的。
● 对象实时状态的复制(也就是对象中基本数据类型的复制)
● 对象引用成员变量的复制。
针对上述两种情况,也就产生了两种复制的效果:
◆浅复制 :针对第一种情况,只复制了基本的数据类型,对于引用类型对象只是单纯的复制了他的
引用还是指向原来引用的对象。java中可以通过Object类的Clone()方法实现浅复制。
◆ 深复制 :针对第二种情况,基本类型和引用类型都进行了新的拷贝,在java中可以通过串行化(实
现Serializable接口),前提是该对象及对象内部的应用类型都是可串行化的。不过实际中
有些对象不必深复制的,可以使用transient进行排除。
举一个简单的例子程序:
考虑这样一个场景,局域网坦克大战的时候,坦克信息的传递,坦克是拥有子弹对象的。
子弹类:
package com.kiritor;
import java.awt.Point;
import java.io.Serializable;
/** 子弹类 */
public class Bullet implements Serializable {
private int tank_id;
private Point point;// 坐标
public int getTank_id() {
return tank_id;
}
public void setTank_id(int tank_id) {
this.tank_id = tank_id;
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
public int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
private int direct;// 子弹方向
}
坦克类:
package com.kiritor;
import java.awt.Point;
import java.io.Serializable;
import java.util.ArrayList;
public class Tank implements Serializable,Cloneable {
private int id;
private Point point;// 坐标
private ArrayList<Bullet> bullets = new ArrayList<Bullet>();// 坦克子弹集
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
public ArrayList<Bullet> getBullets() {
return bullets;
}
public void setBullets(ArrayList<Bullet> bullets) {
this.bullets = bullets;
}
@Override
protected Tank clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (Tank) super.clone();
}
}
测试类:
package com.kiritor;
import java.awt.Point;
public class Prototype {
public static void main(String[] args) throws Exception {
Tank tank = new Tank();
Bullet bullet = new Bullet();
tank.setPoint(new Point(6, 6));// 初始坐标
System.out.println(tank.getPoint().toString());// 坐标
System.out.println(tank.getBullets().size());// 没有子弹
Tank tank_copy1 = (Tank) tank.clone();
System.out.println("第一次克隆");
System.out.println(tank_copy1.getPoint().toString());
System.out.println(tank_copy1.getBullets().size());
System.out.println("改变状态之后克隆");
bullet.setDirect(2);// 给tank增加一个子弹,并设置方向为2
tank.getBullets().add(bullet);
tank.setPoint(new Point(12, 12));// tank的新坐标
Tank tank_copy2 = (Tank) tank.clone();
System.out.println(tank_copy2.getPoint().toString());
System.out.println(tank_copy2.getBullets().size());
System.out.println(tank_copy2.getBullets().get(0).getDirect());
}
}
程序的运行结果: