源码git地址 https://github.com/dlovetco/designMode
问题提出
使用最简单的方法建立出多个相同的复杂对象(以水果为例,创建5个红色的重量为1kg的水果)。
看到这个问题,熟悉java的童鞋可能立马会想到一个东西——克隆。没错,java自身提供用于克隆(深拷贝)的api**Cloneable接口**。自己写的类如果要使用Object的clone()方法,则必须实现Cloneable接口,否则会抛出异常。下面我先用代码演示一下java中clone方法的基操。
clone
package prototype;
public class Prototype {
public static void main(String[] args) throws CloneNotSupportedException {
Fruit apple1 = new Fruit("苹果", "红", 1);
Fruit apple2 = apple1.clone();
System.out.println(apple2);
}
}
class Fruit implements Cloneable{
private String name;
private String color;
private int kilogram;
public Fruit(String name, String color, int kilogram) {
this.name = name;
this.color= color;
this.kilogram = kilogram;
}
@Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", color='" + color+ '\'' +
", kilogram=" + kilogram +
'}';
}
@Override
protected Fruit clone() {
try {
return (Fruit) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
用过clone方法的同学们能看到 我其实在原来方法上做了一点修改。主要是体现一条原则:永远不要让客户端去做任何类库能够替代客户完成的事情
注意:clone方法其实有很多的坑 具体我将会在effective java学习笔记中描述。
原型模式其实也就是这个样子,只不过需要我们自己写clone的内部实现。相比于object的clone方法灵活性更高。
原型模式
public class Prototype {
public static void main(String[] args) throws CloneNotSupportedException {
Fruit apple1 = new Fruit("苹果", "红", 1);
Fruit apple2 = apple1.cloneFruit();
System.out.println(apple2);
}
}
class Fruit implements Cloneable {
private String name;
private String color;
private int kilogram;
public Fruit(String name, String color, int kilogram) {
this.name = name;
this.color = color;
this.kilogram = kilogram;
}
@Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
", kilogram=" + kilogram +
'}';
}
//自己写的拷贝方法
public Fruit cloneFruit() {
return new Fruit(this.name, this.color, this.kilogram);
}
}
此外要注意的一点是:上述例子中类里面只有基本类型的数据,并没有引用类型的数据。如果一个类里面有引用类型的数据,我们使用clone()方法就会出现意想不到的问题。因为clone方法对于引用类型的数据只是浅复制(即只会复制引用)。这样的话如果我们改变了原对象的引用类型数据,克隆对象的相应数据也会被改变。