前言
这篇来讲讲原型模式。
正文
概念
原型模式属于创建型模式,通常被用来创建重复的对象,通过原型来克隆对象,来获取相同的对象。
一般来说是创建对象的代价比较大时,比如对象的属性,设置较多,不方便重新创建,而是从原有对象进行拷贝。
这个模式实现的关键就是clone方法。
原型模式在实际项目中很少单独出现,通常是与工厂模式一起出现,由clone方法创建对象然后由工厂提供给调用者。
实现
我们依然用简单例子来讲讲这个模式。
首先创建的是抽象接口或者类。这里我采用是抽象类加实现Cloneable接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public abstract class Prototype implements Cloneable{ public String id;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
abstract void test();
@Override protected Object clone(){ Object clone = null; try { clone = super.clone(); }catch (CloneNotSupportedException e){ e.printStackTrace(); } return clone; } }
|
然后是具体的原型类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class ConcretePrototype1 extends Prototype{ public ConcretePrototype1() { id = "1"; }
@Override void test() { System.out.println("id: " + id); } } public class ConcretePrototype2 extends Prototype{ public ConcretePrototype2() { id = "2"; }
@Override void test() { System.out.println("id: " + id); } }
|
接着我们创建一个管理类,帮助我们获取原型的克隆,相当于工厂模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class PrototypeManager { private static HashMap<String,Prototype> map = new HashMap<>(); public static Prototype getPrototype(String id){ Prototype prototype = map.get(id); return (Prototype) prototype.clone(); }
public static void init(){ ConcretePrototype1 concretePrototype1 = new ConcretePrototype1(); map.put(concretePrototype1.getId(),concretePrototype1);
ConcretePrototype2 concretePrototype2 = new ConcretePrototype2(); map.put(concretePrototype2.getId(), concretePrototype2); } }
|
最后我们实现一个客户端调用看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Client { public static void main(String[] args) { PrototypeManager.init();
Prototype clonePrototype1 = PrototypeManager.getPrototype("1"); clonePrototype1.test();
Prototype clonePrototype1_ = PrototypeManager.getPrototype("1"); clonePrototype1_.test();
System.out.println(clonePrototype1.hashCode() + " " + clonePrototype1_.hashCode());
} }
|
那最后一行输出是为了看两个对象是否相同,如果是同一个对象那么hashcode应该是相同的,那结果很明显是不同的,所以两个对象只是属性相同,而在内存中的引用不同。
如此我们就结合了原型模式和工厂模式。当然,对于原型管理器也就是PrototypeManager应该实现动态的添加和删除原型,即应该实例化这个对象,并且加上锁来实现并发,这里就不再实现了。
Java中的克隆
这里有一点要说的是,Cloneable接口只起一个作用,并没有实际的方法,它的目的只是告诉JVM可以在这个类上安全的使用clone方法,如果没有实现这个接口,则会抛出CloneNotSupportedException异常。
优缺点
最后我们依旧来讲讲这个模式的优缺点。
优点呢,在于性能高效,并且如果构造函数十分复杂的话还可以不用理会,因为可以直接克隆。
那缺点也十分明显,需要实现cloneable接口,其次就是每个类都必须有一个克隆方法,因为不是所有的类都可以直接使用父类clone方法来进行克隆,复杂的类也许需要手动重新clone方法。然后还有就是在进行拷贝的时候,有可能会出现循环引用的场景,导致栈溢出也是有可能的,因此clone方法并不一定好用。
总结
以上就是关于原型模式的内容。感觉容量不大,但是需要手动写写代码才能更好的理解。