1.原型模式概念
在《Head First Design Patterns》文中是這么介紹原型模式的,“當(dāng)創(chuàng)建指定類實(shí)例的過(guò)程很昂貴或者很復(fù)雜的時(shí)候,可以考慮使用原型模式”,這句話并沒(méi)有解釋原型模式的概念,而是解釋原型模式在什么情況下使用,但我們可以理解為原型模式是用來(lái)創(chuàng)建重復(fù)的對(duì)象,而這些對(duì)象的創(chuàng)建是很復(fù)雜的,所以我們才需要通過(guò)克隆來(lái)生成一個(gè)對(duì)象。原型模式屬于創(chuàng)建型模式。
2.原型模式的作用
原型模式運(yùn)行你通過(guò)復(fù)制現(xiàn)有的實(shí)例來(lái)創(chuàng)建新的實(shí)例(在JAVA中這意味著要使用clone()方法或者反序列化)。
3.使用場(chǎng)景
這種模式是實(shí)現(xiàn)了一個(gè)原型接口,該接口用于創(chuàng)建當(dāng)前對(duì)象的克隆。當(dāng)直接創(chuàng)建對(duì)象的代價(jià)比較大時(shí),則采用這種模式。例如,一個(gè)對(duì)象需要在一個(gè)高代價(jià)的數(shù)據(jù)庫(kù)操作之后被創(chuàng)建。我們可以緩存該對(duì)象,在下一個(gè)請(qǐng)求時(shí)返回它的克隆,在需要的時(shí)候更新數(shù)據(jù)庫(kù),以此來(lái)減少數(shù)據(jù)庫(kù)調(diào)用。
1、類初始化需要消化非常多的資源,這個(gè)資源包括數(shù)據(jù)、硬件資源等。
2、在實(shí)際項(xiàng)目中,原型模式很少單獨(dú)出現(xiàn),一般是和工廠方法模式一起出現(xiàn),通過(guò) clone 的方法創(chuàng)建一個(gè)對(duì)象,然后由工廠方法提供給調(diào)用者。原型模式已經(jīng)與 Java 融為渾然一體,大家可以隨手拿來(lái)使用。
4.優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn)
1、在某些情況下復(fù)制對(duì)象比新建對(duì)象性能更提高。
缺點(diǎn)
1、當(dāng)一個(gè)類引用不支持串行化的間接對(duì)象,使用原型模式也會(huì)變得很復(fù)雜。
5.例子解析
這個(gè)例子是網(wǎng)上找的,上面的許多知識(shí)也是從網(wǎng)上復(fù)制摘抄,既然網(wǎng)上有了我為什么還要寫(xiě)這篇文章,主要是為了記錄我當(dāng)時(shí)看這些文章的一下想法。
這個(gè)例子講的是通過(guò)在客戶端可以通過(guò)指令生成不同的形狀,有三種類型:長(zhǎng)方形,圓形和正方形。生成這些圖形并沒(méi)有需要很大的代價(jià),這里只是舉例說(shuō)明如何實(shí)現(xiàn)原型模式,不要濫用原型模式,要根據(jù)是否符合“當(dāng)直接創(chuàng)建對(duì)象的代價(jià)比較大時(shí)”這個(gè)條件來(lái)使用。
圖形:長(zhǎng)方形,圓形和正方形的父類
public abstract class Shape implements Cloneable {
private String id;
protected String type;
abstract void draw();
public String getType(){
return type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
長(zhǎng)方形
public class Rectangle extends Shape {
public Rectangle(){
type = "Rectangle";
}
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
圓形
public class Circle extends Shape {
public Circle(){
type = "Circle";
}
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
正方形
public class Square extends Shape {
public Square(){
type = "Square";
}
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
這個(gè)類相當(dāng)于一個(gè)工廠,用來(lái)克隆指定的圖形
public class ShapeCache {
private static Hashtable<String, Shape> shapeMap
= new Hashtable<String, Shape>();
public static Shape getShape(String shapeId) {
Shape cachedShape = shapeMap.get(shapeId);
return (Shape) cachedShape.clone();
}
public static void loadCache() {
Circle circle = new Circle();
circle.setId("1");
shapeMap.put(circle.getId(),circle);
Square square = new Square();
square.setId("2");
shapeMap.put(square.getId(),square);
Rectangle rectangle = new Rectangle();
rectangle.setId("3");
shapeMap.put(rectangle.getId(),rectangle);
}
}
客戶端
public class PrototypePatternDemo {
public static void main(String[] args) {
ShapeCache.loadCache();
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());
}
}
6.總結(jié)
在JAVA中應(yīng)該很容易實(shí)現(xiàn)原型模式,只需要實(shí)現(xiàn)Cloneable接口并重寫(xiě)clone方法即可。后面還有幾個(gè)模式,感覺(jué)不怎么常用,就不再寫(xiě)了,后續(xù)如果有時(shí)間或者有更深的了解也許會(huì)繼續(xù)研究。關(guān)于設(shè)計(jì)模式的許多內(nèi)容都是從書(shū)上或者網(wǎng)上找的,有些內(nèi)容也是直接復(fù)制過(guò)來(lái)的。這些內(nèi)容來(lái)源會(huì)在參考文章中給出。