通过复制现有对象来创建新对象,而不是通过新建类实例的方式。这种模式特别适用于创建成本较高的对象。
比如,你需要创建一个对象,但是这个对象的实际创建过程较为复杂,可能需要调用多个数据库,根据数据库里面的配置来进行生成。那么这个时候你就可以在初次创建了这个对象之后将其复制一份,缓存起来,下一次就可以使用缓存里面的数据了。但是实际使用的时候需要考虑到用版本号等机制保证一下缓存的一致性,这里只说明生成对象的方式。
原型模式在复制对象时的主要依赖的就是拷贝机制,这里我们用的都是浅拷贝。但是String对象比较例外,它具有不可变性,在复制的对象中的确只是复制了原有对象的string的引用。但是,如果原始对象中的string发生了修改,会给原始对象一个新的string。因此,变相的深拷贝的效果。
代码地址:github.com/YaYiXiBa/Ja...
scala
public class Rectangle extends Shape{
public Rectangle(){
type = "Rectangle";
}
@Override
void draw() {
System.out.println("draw rectangle");
}
}
首先,对不同的形状都进行了抽象。这样就只需要让抽象父类去实现Clonable接口就行了。
typescript
public abstract class Shape implements Cloneable {
private String id;
protected String type;
abstract void draw();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj;
obj = super.clone();
return obj;
}
}
重写Object的方法,如果有引用数据类型的话要记得使用深拷贝。
scss
public class ShapeCache {
private static Hashtable<String, Shape> shapeCache = new Hashtable<>();
public static Shape getShape(String shapeId) {
Shape shape = shapeCache.get(shapeId);
try {
return (Shape) shape.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public static void load() {
Circle circle = new Circle();
circle.setId("1");
shapeCache.put(circle.getId(),circle);
Square square = new Square();
square.setId("2");
shapeCache.put(square.getId(),square);
Rectangle rectangle = new Rectangle();
rectangle.setId("3");
shapeCache.put(rectangle.getId(),rectangle);
}
}
其实代码的核心步骤就是在return (Shape) shape.clone();虽然我们缓存了对象,但是不将原始对象返回,而是通过克隆返回新的对象,这是为了防止客户端修改对象,导致我们缓存的对象发生了变化。
ini
public class Client {
public static void main(String[] args) {
ShapeCache.load();
Shape clonedShape = (Shape) ShapeCache.getShape("1");
System.out.println("Shape : " + clonedShape.getType());
Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
System.out.println("Shape : " + clonedShape2.getType());
Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
System.out.println("Shape : " + clonedShape3.getType());
Shape circle1 = ShapeCache.getShape("1");
Shape circle2 = ShapeCache.getShape("1");
System.out.println(circle1 == circle2);
}
}
输出结果:
Shape : Circle
Shape : Square
Shape : Rectangle
false
Process finished with exit code 0
可以发现circle1、circle2是不相等的。
原来我所以为的原型模式,就是我给对方一个对象,他返回给我一个一样的。现在才知道,以上写的是注册表的形式,通过ID来获取原型。。。。