創(chuàng)建模式(Creational Pattern)是對(duì)類的實(shí)例化過程的抽象化捎迫。
創(chuàng)建模式分為類創(chuàng)建模式和對(duì)象的創(chuàng)建模式兩種鞠柄。
簡單工廠模式(Simple Factory)
靜態(tài)工廠方法模式(Static Factory Method Pattern)
工廠方法模式(Factory Method)
多態(tài)性工廠模式(Polymorphic Factory)
虛擬構(gòu)造子模式(Virtual Constructor)
抽象工廠模式(Abstract Factory)
工具箱模式(Kit/Toolkit)
單例模式(Singleton)
多例模式(Multition Pattern)
建造模式(Builder)
原始模型模式(Protorype)
簡單工廠模式
類圖
/**
* <b>Description:</b> 抽象產(chǎn)品Concrete Product <br>
*/
public interface Fruit {
void grow();
void harvest();
void plant();
}
/**
* <b>Description:</b> 具體產(chǎn)品Product <br>
*/
public class Apple implements Fruit {
private int treeAge;
@Override
public void grow() {
Log.i("","Apple is growing...");
}
@Override
public void harvest() {
Log.i("","Apple has been harvested.");
}
@Override
public void plant() {
Log.i("","Apple has been planted.");
}
public int getTreeAge() {
return treeAge;
}
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
}
/**
* <b>Description:</b> 具體產(chǎn)品Product <br>
*/
public class Grape implements Fruit {
private boolean seedless;
@Override
public void grow() {
Log.i("", "Grape is growing...");
}
@Override
public void harvest() {
Log.i("", "Grape has been harvested.");
}
@Override
public void plant() {
Log.i("", "Grape has been planted.");
}
public boolean isSeedless() {
return seedless;
}
public void setSeedless(boolean seedless) {
this.seedless = seedless;
}
}
/**
* <b>Description:</b> 具體產(chǎn)品Product <br>
*/
public class Strawberry implements Fruit {
@Override
public void grow() {
Log.i("", "Apple is growing...");
}
@Override
public void harvest() {
Log.i("", "Apple has been harvested.");
}
@Override
public void plant() {
Log.i("", "Apple has been planted.");
}
}
/**
* <b>Description:</b> 工廠類Creator(上帝類God Class) <br>
* 模式的核心砌些。含有必要的判斷邏輯撑瞧,可以決定在什么時(shí)候創(chuàng)建哪一個(gè)產(chǎn)品類的實(shí)例镜雨。
*/
public class FruitGardener {
public static Fruit factory(String which) throws BadFruitException {
if (which.equalsIgnoreCase("apple")) {
return new Apple();
}
if (which.equalsIgnoreCase("strawberry")) {
return new Strawberry();
}
if (which.equalsIgnoreCase("grape")) {
return new Grape();
} else {
throw new BadFruitException("");
}
}
}
/**
* <b>Description:</b> 異常類 <br>
*/
public class BadFruitException extends Exception {
public BadFruitException(String message) {
super(message);
}
}
工廠方法模式
類圖
/**
* <b>Description:</b> 抽象工廠Creator <br>
* 模式的核心角虫。
*/
public interface FruitGardener {
Fruit factory();
}
/**
* <b>Description:</b> 具體工廠Concrete Creator <br>
*/
public class AppleGardener implements FruitGardener {
@Override
public Fruit factory() {
return new Apple();
}
}
/**
* <b>Description:</b> 具體工廠Concrete Creator <br>
*/
public class GrapeGardener implements FruitGardener {
@Override
public Fruit factory() {
return new Grape();
}
}
/**
* <b>Description:</b> 具體工廠Concrete Creator <br>
*/
public class StrawberryGardener implements FruitGardener {
@Override
public Fruit factory() {
return new Strawberry();
}
}
抽象工廠模式
類圖
/**
* <b>Description:</b> 抽象產(chǎn)品 <br>
*/
public interface Fruit {
}
/**
* <b>Description:</b> 具體產(chǎn)品類 <br>
*/
public class NorthernFruit implements Fruit {
private String name;
public NorthernFruit(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* <b>Description:</b> 具體產(chǎn)品類 <br>
*/
public class TropicalFruit implements Fruit {
private String name;
public TropicalFruit(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* <b>Description:</b> 抽象產(chǎn)品 <br>
*/
public interface Veggie {
}
/**
* <b>Description:</b> 具體產(chǎn)品類 <br>
*/
public class NorthernVeggie implements Veggie {
private String name;
public NorthernVeggie(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* <b>Description:</b> 具體產(chǎn)品類 <br>
*/
public class TropicalVeggie implements Veggie {
private String name;
public TropicalVeggie(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* <b>Description:</b> 抽象工廠 <br>
* 模式的核心。
* 1.一個(gè)系統(tǒng)不應(yīng)當(dāng)依賴于產(chǎn)品類的實(shí)例如何被創(chuàng)建殴胧、組合和表達(dá)的細(xì)節(jié)渗稍。(所有工廠模式)
* 2.這個(gè)系統(tǒng)的產(chǎn)品有多余一個(gè)的產(chǎn)品族佩迟,而系統(tǒng)只消費(fèi)其中某一個(gè)產(chǎn)品族的產(chǎn)品。(原始用意)
* 3.同屬于同一個(gè)產(chǎn)品族的產(chǎn)品是在一起使用的竿屹,這一約束必須在系統(tǒng)的設(shè)計(jì)中體現(xiàn)出來报强。
* 4.系統(tǒng)提供一個(gè)產(chǎn)品類的庫,所有的產(chǎn)品以同樣的接口出現(xiàn)拱燃,從而使客戶端不依賴于實(shí)現(xiàn)秉溉。
*/
public interface Gardener {
Fruit createFruit(String name);
Veggie createVeggie(String name);
}
/**
* <b>Description:</b> 具體工廠類 <br>
*/
public class NorthernGardener implements Gardener {
@Override
public Fruit createFruit(String name) {
return new NorthernFruit(name);
}
@Override
public Veggie createVeggie(String name) {
return new NorthernVeggie(name);
}
}
/**
* <b>Description:</b> 具體工廠類 <br>
*/
public class TropicalGardener implements Gardener{
@Override
public Fruit createFruit(String name) {
return new TropicalFruit(name);
}
@Override
public Veggie createVeggie(String name) {
return new TropicalVeggie(name);
}
}
單例模式
特點(diǎn)
1.單例類只能有一個(gè)實(shí)例。
2.單例類必須自己創(chuàng)建自己的唯一實(shí)例扼雏。
3.單例類必須給所有其他對(duì)象提供這一實(shí)例坚嗜。
雖然單例模式中的單例類被限定只能有一個(gè)實(shí)例,但是單例模式和單例類可以很容易被推廣到任意且有有限多個(gè)實(shí)例的情況诗充,這時(shí)候稱它為多例模式和多例類。
餓漢式單例類
懶漢式單例類
登記式單例類
餓漢式單例類
/**
* <b>Description:</b> 餓漢式單例類 <br>
* 餓漢式單例類在自己被加載時(shí)將自己實(shí)例化诱建。
* 即便加載器是靜態(tài)的蝴蜓,在餓漢式單例類加載時(shí)仍會(huì)將自己實(shí)例化。
* 單從資源利用率角度來講俺猿,這個(gè)比懶漢式單例類稍差些茎匠。
* 從速度和反應(yīng)時(shí)間角度來講,則比懶漢式單例類稍好些押袍。
* <p>
* 不可繼承
*/
public class EagerSingleton {
private static final EagerSingleton mInstance = new EagerSingleton();
/**
* 私有的默認(rèn)構(gòu)造子
*/
private EagerSingleton() {
}
/**
* 靜態(tài)工廠方法
*
* @return
*/
public static EagerSingleton getInstance() {
return mInstance;
}
}
懶漢式單例類
/**
* <b>Description:</b> 懶漢式單例類 <br>
* 懶漢式單例類在實(shí)例化時(shí)诵冒,必須處理好在多個(gè)線程同時(shí)抽次引用此類時(shí)訪問限制問題,特別是當(dāng)單例類作為資源控制器在實(shí)例化時(shí)必然涉及資源初始化谊惭,而資源初始化很有可能耗費(fèi)時(shí)間汽馋。
* 這意味著出現(xiàn)多線程同時(shí)首次引用此類的幾率變得較大。
* <p>
* 不可繼承
*/
public class LazySingleton {
private static LazySingleton mInstance = null;
/**
* 私有的默認(rèn)構(gòu)造子圈盔,保證外界無法直接實(shí)例化
*/
private LazySingleton() {
}
/**
* 靜態(tài)工廠方法豹芯,返還此類的唯一實(shí)例
*
* @return
*/
synchronized public static LazySingleton getInstance() {
if (mInstance == null) {
mInstance = new LazySingleton();
}
return mInstance;
}
}
登記式單例類
/**
* <b>Description:</b> 登記式單例類 <br>
* 餓漢式
* 可繼承
*/
public class RegSingleton {
static private HashMap mRegistry = new HashMap();
static {
RegSingleton x = new RegSingleton();
mRegistry.put(x.getClass().getName(), x);
}
/**
* 保護(hù)的默認(rèn)構(gòu)造子
*/
protected RegSingleton() {
}
/**
* 靜態(tài)工廠方法,返還此類的唯一實(shí)例
*
* @param name
* @return
*/
static public RegSingleton getInstance(String name) {
if (name == null) {
name = "pr.tongson.pattern.Singleton.RegSingleton";
}
if (mRegistry.get(name) == null) {
try {
mRegistry.put(name, Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return (RegSingleton) mRegistry.get(name);
}
/**
* 一些示意性的商業(yè)方法
*
* @return
*/
public String about() {
return "Hello, I am RegSigleton.";
}
}
/**
* <b>Description:</b> 登記式單例類 <br>
* 懶漢式
* 子類
*/
public class RegSigletonChild extends RegSingleton {
public RegSigletonChild() {
}
static public RegSigletonChild getInstance() {
return (RegSigletonChild) RegSingleton.getInstance("pr.tongson.pattern.Singleton.RegSigletonChild");
}
/**
* 一些示意性的商業(yè)方法
*
* @return
*/
@Override
public String about() {
return "Hello, I am RegSigletonChild.";
}
}
在什么情況下使用單例模式
必要條件:在一個(gè)系統(tǒng)要求一個(gè)類只有一個(gè)實(shí)例時(shí)才應(yīng)當(dāng)使用單例模式驱敲。
有狀態(tài)的單例類
User類
沒有狀態(tài)的單例類(提供工具性函數(shù)的對(duì)象)
Uitl類
屬性類
多例模式
多例模式中的多例類可以有多個(gè)實(shí)例铁蹈,而且多例類必須自己創(chuàng)建、管理自己的實(shí)例众眨,并向外界提供自己的實(shí)例握牧。
所謂多例模式實(shí)際上就是單例模式的自然推廣。
特點(diǎn):
1.多例類可有多個(gè)實(shí)例娩梨。
2.多例類必須自己創(chuàng)建沿腰、管理自己的實(shí)例,并向外界提供自己的實(shí)例姚建。
public class Die {
private static Die die1 = new Die();
private static Die die2 = new Die();
/**
* 私有的構(gòu)造子保證外界無法直接將此類實(shí)例化
*/
private Die() {
}
/**
* 工廠方法
*
* @param whichOne
* @return
*/
public static Die getInstance(int whichOne) {
if (whichOne == 1) {
return die1;
} else {
return die2;
}
}
/**
* 擲骰子矫俺,返回一個(gè)在1~6之間的隨機(jī)數(shù)
*
* @return
*/
public synchronized int dice() {
Date date = new Date();
Random random = new Random(date.getTime());
int value = random.nextInt();
value = Math.abs(value);
value = value % 6;
value += 1;
return value;
}
}
public class Client {
private static Die die1, die2;
public static void main(String[] args) {
die1 = Die.getInstance(1);
die2 = Die.getInstance(2);
die1.dice();
die2.dice();
}
}
無上限多例模式
有狀態(tài)的和沒有狀態(tài)的多例類
Lingual Resource
序列鍵生成器
沒有數(shù)據(jù)庫的情況
有數(shù)據(jù)庫的情況
鍵值的緩存方案
有緩存的多序列鍵生成器
建造者模式
類圖
/**
* <b>Description:</b> 產(chǎn)品 <br>
* 復(fù)雜對(duì)象
* 一般來說,每有一個(gè)產(chǎn)品類,就有一個(gè)相應(yīng)的具體建造類厘托。
* 這些產(chǎn)品應(yīng)當(dāng)有一樣數(shù)目的零件友雳,而每有一個(gè)零件就相當(dāng)?shù)卦谒械慕ㄔ煺呓巧镉幸粋€(gè)構(gòu)造方法。
*/
public class Product {
//Anything pertaining to this product
}
/**
* <b>Description:</b> 抽象建造者 <br>
* 給出一個(gè)抽象接口铅匹,以規(guī)范產(chǎn)品對(duì)象的各個(gè)組成成分的建造押赊。
* 一般而言,此接口獨(dú)立于應(yīng)用程序的商業(yè)邏輯包斑。
*/
abstract public class Builder {
/**
* 產(chǎn)品零件建造方法
*/
public abstract void buildPart1();
/**
* 產(chǎn)品零件建造方法
*/
public abstract void buildPart2();
/**
* 產(chǎn)品返還方法
*
* @return
*/
public abstract Product retrieveResult();
}
/**
* <b>Description:</b> 具體建造者 <br>
* 創(chuàng)建產(chǎn)品實(shí)例
*/
public class ConcreteBuilder extends Builder {
private Product mProduct = new Product();
/**
* 產(chǎn)品零件建造方法
*/
@Override
public void buildPart1() {
//build the first part of the product
}
/**
* 產(chǎn)品零件建造方法
*/
@Override
public void buildPart2() {
//build the second part of the product
}
/**
* 產(chǎn)品返還方法
*
* @return
*/
@Override
public Product retrieveResult() {
return mProduct;
}
}
/**
* <b>Description:</b> 導(dǎo)演者 <br>
* 調(diào)用具體建造者以創(chuàng)建產(chǎn)品對(duì)象流礁。
*/
public class Director {
private Builder mBuilder;
/**
* 產(chǎn)品構(gòu)造方法,負(fù)責(zé)調(diào)用各個(gè)零件構(gòu)造方法
*/
public void construct() {
mBuilder = new ConcreteBuilder();
mBuilder.buildPart1();
mBuilder.buildPart2();
mBuilder.retrieveResult();
//continue with othor code
}
}
空的零件建造方法(ConcreteBuilder)
省略抽象建造者角色(Builder)
省略導(dǎo)演者角色(Director)
過渡到模板(Template)方法模式
合并建造者角色和產(chǎn)品角色
建造者角色可以有多個(gè)產(chǎn)品構(gòu)造方法
在什么情況下使用建造模式
在以下情況下應(yīng)當(dāng)使用建造模式:
1.需要生成的產(chǎn)品對(duì)象有復(fù)雜的內(nèi)部結(jié)構(gòu)罗丰。每一個(gè)內(nèi)部成分本身可以是對(duì)象神帅,也可以僅僅是一個(gè)對(duì)象(即產(chǎn)品對(duì)象)的一個(gè)組成成分。
2.需要生成的產(chǎn)品對(duì)象的屬性相互依賴萌抵。建造者模式可以強(qiáng)制實(shí)行一種分步驟進(jìn)行的建造過程找御,因此,如果產(chǎn)品對(duì)象的一個(gè)屬性必須在另一個(gè)屬性被賦值之后才可以被賦值绍填,使用建造模式便是一個(gè)很好的設(shè)計(jì)思想霎桅。
有時(shí)產(chǎn)品對(duì)象的屬性并無彼此依賴的關(guān)系,但是在產(chǎn)品的屬性沒有確定之前讨永,產(chǎn)品對(duì)象不能使用滔驶。這時(shí)產(chǎn)品對(duì)象的實(shí)例化,屬性的賦值和使用仍然是分步驟進(jìn)行的卿闹。因此揭糕,創(chuàng)建模式仍然有意義。
3.在對(duì)象創(chuàng)建過程中會(huì)使用到系統(tǒng)中的其他一些對(duì)象比原,這些對(duì)象在產(chǎn)品對(duì)象的創(chuàng)建過程中不易得到插佛。
同時(shí),使用建造模式主要有以下的效果:
- 建造模式的使用使得產(chǎn)品的內(nèi)部表象可以獨(dú)立地變化量窘。使用建造模式可以使客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié)雇寇。
- 每一個(gè)Builder 都相對(duì)獨(dú)立,而與其他的Builder無關(guān)蚌铜。
- 模式所建造的最終產(chǎn)品更易于控制锨侯。
原始模型模式
簡單形式
/**
* <b>Description:</b> 抽象原型 <br>
* 給出所有的具體原型類所需的接口
*/
public interface Prototype extends Cloneable {
Prototype clone();
}
/**
* <b>Description:</b> 具體原型 <br>
* 被復(fù)制的對(duì)象
* 需要實(shí)現(xiàn)抽象的原型角色所要求的接口。
*/
public class ConcretePrototype implements Prototype {
/**
* 克隆方法
*
* @return
*/
@Override
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
/**
* <b>Description:</b> 客戶 <br>
* 提出創(chuàng)建對(duì)象的請(qǐng)求
*/
public class Client {
private Prototype mPrototype;
public void operation(Prototype example) {
Prototype copytype = example.clone();
}
}
登記形式
/**
* <b>Description:</b> 原型管理器 <br>
* 記錄每一個(gè)被創(chuàng)建的對(duì)象
*/
public class PrototypeManager {
private Vector objects = new Vector();
/**
* 聚集管理方法:增加一個(gè)新的對(duì)象
*
* @param object
*/
public void add(Prototype object) {
objects.add(object);
}
/**
* 聚集管理方法:取出聚集中的一個(gè)對(duì)象
*
* @param i
* @return
*/
public Prototype get(int i) {
return (Prototype) objects.get(i);
}
/**
* 聚集管理方法:給出聚集的大小
*
* @return
*/
public int getSize() {
return objects.size();
}
}
/**
* <b>Description:</b> 客戶端 <br>
* 客戶端類向管理員提出創(chuàng)建對(duì)象的請(qǐng)求
*/
public class Client {
private PrototypeManager mPrototypeManager;
private Prototype mPrototype;
public void registerPrototype() {
mPrototype = new ConcretePrototype();
Prototype copyType = (Prototype) mPrototype.clone();
mPrototypeManager.add(copyType);
}
}
淺復(fù)制
有一些不同
深復(fù)制
完全相同冬殃,但也不是同一個(gè)對(duì)象囚痴,需要java.io.Serializable