原型模式(Prototype Pattern)是用于創(chuàng)建重復(fù)的對象,同時又能保證性能呵哨。這種類型的設(shè)計模式屬于創(chuàng)建型模式嗤攻,它提供了一種創(chuàng)建對象的最佳方式。
這種模式是實現(xiàn)了一個原型接口(java.lang.Cloneable)屿愚,該接口用于創(chuàng)建當(dāng)前對象的克隆汇跨。當(dāng)直接創(chuàng)建對象的代價比較大時,則采用這種模式渺鹦。例如扰法,一個對象需要在一個高代價的數(shù)據(jù)庫操作之后被創(chuàng)建蛹含。我們可以緩存該對象毅厚,在下一個請求時返回它的克隆,在需要的時候更新數(shù)據(jù)庫浦箱,以此來減少數(shù)據(jù)庫調(diào)用吸耿。
原型模式組成
原型(Prototype):實際對象的原型(Movie、Album酷窥、Show)咽安;
原型注冊緩存(Prototype Registry):用于內(nèi)存中緩存具體的原型對象(PrototypeFactory#protoTypes);
客戶端:負(fù)責(zé)從注冊表中獲取原型對象蓬推。
案例實踐
自定義一個接口類型妆棒,繼承Cloneable接口,作為原型模式的接口類型沸伏。
package com.iblog.pattern.prototype;
/**
* ProtoType pattern interface declaration.
*/
public interface ProtoTypeCapable extends Cloneable {
ProtoTypeCapable clone() throws CloneNotSupportedException;
}
假設(shè)Movie糕珊、Album、Show對象的創(chuàng)建非常復(fù)雜毅糟,我們通過原型模式來覆蓋其對象創(chuàng)建红选。
package com.iblog.pattern.prototype;
public class Movie implements ProtoTypeCapable {
private String name;
public ProtoTypeCapable clone() throws CloneNotSupportedException {
// clone a Movie object in this.
return (Movie) super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "movie => [name:" + name + "]";
}
}
package com.iblog.pattern.prototype;
public class Album implements ProtoTypeCapable {
private String name;
@Override
public ProtoTypeCapable clone() throws CloneNotSupportedException {
return (Album) super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "album => [name:" + name + "]";
}
}
package com.iblog.pattern.prototype;
public class Show implements ProtoTypeCapable {
private String name;
@Override
public ProtoTypeCapable clone() throws CloneNotSupportedException {
return (Show) super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Show => [name:" + name + "]";
}
}
在案例中,我們將原型對象注冊地址與原型客戶端都封裝在一個工廠操作類中姆另。
package com.iblog.pattern.prototype;
import java.util.HashMap;
import java.util.Map;
public class ProtoTypeFactory {
public static class ModelType {
public static final String MOVIE = "Movie";
public static final String ALBUM = "Album";
public static final String SHOW = "Show";
}
private static Map<String, ProtoTypeCapable> protoTypes = new HashMap<>();
static {
protoTypes.put(ModelType.MOVIE, new Movie());
protoTypes.put(ModelType.ALBUM, new Album());
protoTypes.put(ModelType.SHOW, new Show());
}
public static ProtoTypeCapable getInstance(final String type) throws CloneNotSupportedException {
return protoTypes.get(type).clone();
}
}
這樣在Java中可以通過在ProtoTypeFactory#getInstance(type)方法很方便克隆一個目標(biāo)對象喇肋。
總結(jié)
原型模式屬于創(chuàng)建型模式的一種,但是在我們實際應(yīng)用中場景并不廣泛迹辐,只有在對象創(chuàng)建十分復(fù)雜的情景中才考慮原型模式蝶防;此外需要注意原型模式在克隆對象時候?qū)τ谄渲械膶傩宰侄蔚目截悺?/p>
github: pattern-example