設(shè)計模式-創(chuàng)建模式(Creational Pattern)

創(chuàng)建模式(Creational Pattern)是對類的實例化過程的抽象化。
創(chuàng)建模式分為類創(chuàng)建模式對象的創(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)

簡單工廠模式

類圖

簡單工廠模式的結(jié)構(gòu)
/**
 * <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>
 * 模式的核心。含有必要的判斷邏輯,可以決定在什么時候創(chuàng)建哪一個產(chǎn)品類的實例。
 */
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);
    }
}

工廠方法模式

類圖

工廠方法模式的結(jié)構(gòu)
/**
 * <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();
    }
}

抽象工廠模式

類圖

抽象工廠模式的結(jié)構(gòu)
/**
 * <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.一個系統(tǒng)不應(yīng)當(dāng)依賴于產(chǎn)品類的實例如何被創(chuàng)建、組合和表達的細(xì)節(jié)。(所有工廠模式)
 * 2.這個系統(tǒng)的產(chǎn)品有多余一個的產(chǎn)品族,而系統(tǒng)只消費其中某一個產(chǎn)品族的產(chǎn)品。(原始用意)
 * 3.同屬于同一個產(chǎn)品族的產(chǎn)品是在一起使用的,這一約束必須在系統(tǒng)的設(shè)計中體現(xiàn)出來。
 * 4.系統(tǒng)提供一個產(chǎn)品類的庫,所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于實現(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);
    }
}

單例模式

特點

1.單例類只能有一個實例。
2.單例類必須自己創(chuàng)建自己的唯一實例。
3.單例類必須給所有其他對象提供這一實例。
雖然單例模式中的單例類被限定只能有一個實例,但是單例模式和單例類可以很容易被推廣到任意且有有限多個實例的情況,這時候稱它為多例模式和多例類。

餓漢式單例類
懶漢式單例類
登記式單例類

餓漢式單例類

/**
 * <b>Description:</b> 餓漢式單例類 <br>
 * 餓漢式單例類在自己被加載時將自己實例化。
 * 即便加載器是靜態(tài)的,在餓漢式單例類加載時仍會將自己實例化。
 * 單從資源利用率角度來講,這個比懶漢式單例類稍差些。
 * 從速度和反應(yīng)時間角度來講,則比懶漢式單例類稍好些。
 * <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>
 * 懶漢式單例類在實例化時,必須處理好在多個線程同時抽次引用此類時訪問限制問題,特別是當(dāng)單例類作為資源控制器在實例化時必然涉及資源初始化,而資源初始化很有可能耗費時間。
 * 這意味著出現(xiàn)多線程同時首次引用此類的幾率變得較大。
 * <p>
 * 不可繼承
 */
public class LazySingleton {

    private static LazySingleton mInstance = null;

    /**
     * 私有的默認(rèn)構(gòu)造子,保證外界無法直接實例化
     */
    private LazySingleton() {
    }

    /**
     * 靜態(tài)工廠方法,返還此類的唯一實例
     *
     * @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);
    }

    /**
     * 保護的默認(rèn)構(gòu)造子
     */
    protected RegSingleton() {

    }

    /**
     * 靜態(tài)工廠方法,返還此類的唯一實例
     *
     * @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.";
    }
}

在什么情況下使用單例模式

必要條件:在一個系統(tǒng)要求一個類只有一個實例時才應(yīng)當(dāng)使用單例模式。

有狀態(tài)的單例類

User類

沒有狀態(tài)的單例類(提供工具性函數(shù)的對象)

Uitl類

屬性類

多例模式

多例模式中的多例類可以有多個實例,而且多例類必須自己創(chuàng)建、管理自己的實例,并向外界提供自己的實例。
所謂多例模式實際上就是單例模式的自然推廣。

特點:

1.多例類可有多個實例。
2.多例類必須自己創(chuàng)建、管理自己的實例,并向外界提供自己的實例。

public class Die {
    private static Die die1 = new Die();
    private static Die die2 = new Die();

    /**
     * 私有的構(gòu)造子保證外界無法直接將此類實例化
     */
    private Die() {
    }

    /**
     * 工廠方法
     *
     * @param whichOne
     * @return
     */
    public static Die getInstance(int whichOne) {
        if (whichOne == 1) {
            return die1;
        } else {
            return die2;
        }
    }

    /**
     * 擲骰子,返回一個在1~6之間的隨機數(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ù)庫的情況
鍵值的緩存方案
有緩存的多序列鍵生成器

建造者模式

類圖

構(gòu)建者模式的結(jié)構(gòu)
/**
 * <b>Description:</b> 產(chǎn)品 <br>
 * 復(fù)雜對象
 * 一般來說,每有一個產(chǎn)品類,就有一個相應(yīng)的具體建造類。
 * 這些產(chǎn)品應(yīng)當(dāng)有一樣數(shù)目的零件,而每有一個零件就相當(dāng)?shù)卦谒械慕ㄔ煺呓巧镉幸粋€構(gòu)造方法。
 */
public class Product {
    //Anything pertaining to this product
}
/**
 * <b>Description:</b> 抽象建造者 <br>
 * 給出一個抽象接口,以規(guī)范產(chǎn)品對象的各個組成成分的建造。
 * 一般而言,此接口獨立于應(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)品實例
 */
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)品對象。
 */
public class Director {
    private Builder mBuilder;

    /**
     * 產(chǎn)品構(gòu)造方法,負(fù)責(zé)調(diào)用各個零件構(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)品角色

建造者角色可以有多個產(chǎn)品構(gòu)造方法

在什么情況下使用建造模式

在以下情況下應(yīng)當(dāng)使用建造模式:
1.需要生成的產(chǎn)品對象有復(fù)雜的內(nèi)部結(jié)構(gòu)。每一個內(nèi)部成分本身可以是對象,也可以僅僅是一個對象(即產(chǎn)品對象)的一個組成成分。
2.需要生成的產(chǎn)品對象的屬性相互依賴。建造者模式可以強制實行一種分步驟進行的建造過程,因此,如果產(chǎn)品對象的一個屬性必須在另一個屬性被賦值之后才可以被賦值,使用建造模式便是一個很好的設(shè)計思想。
有時產(chǎn)品對象的屬性并無彼此依賴的關(guān)系,但是在產(chǎn)品的屬性沒有確定之前,產(chǎn)品對象不能使用。這時產(chǎn)品對象的實例化,屬性的賦值和使用仍然是分步驟進行的。因此,創(chuàng)建模式仍然有意義。
3.在對象創(chuàng)建過程中會使用到系統(tǒng)中的其他一些對象,這些對象在產(chǎn)品對象的創(chuàng)建過程中不易得到。

同時,使用建造模式主要有以下的效果:

  • 建造模式的使用使得產(chǎn)品的內(nèi)部表象可以獨立地變化。使用建造模式可以使客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié)。
  • 每一個Builder 都相對獨立,而與其他的Builder無關(guān)。
  • 模式所建造的最終產(chǎn)品更易于控制。

原始模型模式

簡單形式

/**
 * <b>Description:</b> 抽象原型 <br>
 * 給出所有的具體原型類所需的接口
 */
public interface Prototype extends Cloneable {
    Prototype clone();
}

/**
 * <b>Description:</b> 具體原型 <br>
 * 被復(fù)制的對象
 * 需要實現(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)建對象的請求
 */
public class Client {
    private Prototype mPrototype;

    public void operation(Prototype example) {
        Prototype copytype = example.clone();
    }
}

登記形式

/**
 * <b>Description:</b> 原型管理器 <br>
 * 記錄每一個被創(chuàng)建的對象
 */
public class PrototypeManager {
    private Vector objects = new Vector();

    /**
     * 聚集管理方法:增加一個新的對象
     *
     * @param object
     */
    public void add(Prototype object) {
        objects.add(object);
    }

    /**
     * 聚集管理方法:取出聚集中的一個對象
     *
     * @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)建對象的請求
 */
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ù)制

完全相同,但也不是同一個對象,需要java.io.Serializable

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容