国产成人久久777777-国产农村妇女毛片精品久久-精品少妇人妻AV一区二区-少妇人妻精品一区二区三区-无码人妻精品一区二区

工廠模式 -電腦資料

電腦資料 時間:2019-01-01 我要投稿
【www.gydabaoji.com - 電腦資料】

   

工廠模式
    標簽: Java與設計模式


    工廠模式

    用工廠方法代替了new操作, 將選擇實現類,創建對象統一管理和控制.從而將調用者(Client)與實現類進行解耦.實現了創建者與調用者分離;

使用場景

    JDK中Calendar的getInstance方法; JDBC中Connection對象的獲取; MyBatis中SqlSessionFactory創建SqlSession; SpringIoC容器創建并管理Bean對象; 反射Class對象的newInstance; ….


靜態工廠模式

    靜態工廠模式是工廠模式中最簡單的一種,他可以用比較簡單的方式隱藏創建對象的細節,一般只需要告訴工廠類所需要的類型,工廠類就會返回需要的產品類,而客戶端看到的也只是產品的抽象對象(interface),因此無需關心到底是返回了哪個子類

    我們以運算符類為例, 解釋靜態工廠模式.

   

    Operator接口

<code class="hljs" scala="">/** * 運算符接口 * Created by jifang on 15/12/7. */public interface Operator<t>{    T getResult(T... args);}</t></code>
實現類
<code axapta="" class="hljs">public class AddOperator implements Operator<integer>{    @Override    public Integer getResult(Integer... args) {        int result = 0;        for (int arg : args) {            result += arg;        }        return result;    }}</integer></code>
<code axapta="" class="hljs">public class MultiOperator implements Operator<integer>{    @Override    public Integer getResult(Integer... args) {        int result = 1;        for (int arg : args) {            result *= arg;        }        return result;    }}</integer></code>
工廠
<code class="hljs" java="">/** * 靜態工廠(注: 只返回產品的抽象[即接口]) * 包含兩種實現策略 * 1. 根據傳入的operator名進行實例化對象 * 2. 直接調用相應的構造實例的方法 * Created by jifang on 15/12/7. */public class OperatorFactory {    public static Operator<integer>createOperator(String operName) {        Operator<integer>operator;        switch (operName) {            case +:                perator = new AddOperator();                break;            case *:                perator = new MultiOperator();                break;            default:                throw new RuntimeException(Wrong Operator Name:  + operName);        }        return operator;    }    /* ** 第二種實現策略 ** */    public static Operator<integer>createAddOper() {        return new AddOperator();    }    public static Operator<integer>createMultiOper() {        return new MultiOperator();    }}</integer></integer></integer></integer></code>
Client
<code class="hljs" cs="">public class Client {    @Test    public void testAdd() {        Operator<integer>operator = OperatorFactory.createOperator(+);        System.out.println(operator.getResult(1, 2, 3, 4, 6));    }    @Test    public void testMultiplication() {        Operator<integer>operator = OperatorFactory.createOperator(*);        System.out.println(operator.getResult(1, 2, 3, 4, 6));    }    @Test    public void testAddName(){        Operator<integer>operator = OperatorFactory.createAddOper();        System.out.println(operator.getResult(1, 2, 3, 4, 6));    }    @Test    public void testMultiplicationName() {        Operator<integer>operator = OperatorFactory.createMultiOper();        System.out.println(operator.getResult(1, 2, 3, 4, 6));    }}</integer></integer></integer></integer></code>

    優點

隱藏了對象創建的細節,將產品的實例化過程放到了工廠中實現,

工廠模式

。 客戶端基本不用關心使用的是哪個產品,只需要知道用工廠的那個方法(或傳入什么參數)就行了. 方便添加新的產品子類,每次只需要修改工廠類傳遞的類型值就行了。 遵循了依賴倒轉原則。

    缺點

適用于產品子類型差不多, 使用的方法名都相同的情況. 每添加一個產品子類,都必須在工廠類中添加一個判斷分支(或一個方法),這違背了OCP(開放-封閉原則)

工廠方法模式

    由于靜態工廠方法模式不滿足OCP, 因此就出現了工廠方法模式; 工廠方法模式和靜態工廠模式最大的不同在于:靜態工廠模式只有一個(對于一個項目/獨立模塊)只有一個工廠類, 而工廠方法模式則有一組實現了相同接口的工廠類.

   

工廠
<code class="hljs" scala="">/** * Created by jifang on 15/12/7. */public interface Factory<t>{    Operator<t>createOperator();}</t></t></code>
工廠實現
<code class="hljs" php="">/** * 加法運算符工廠 * Created by jifang on 15/12/7. */public class AddFactory implements Factory<integer>{    @Override    public Operator<integer>createOperator() {        return new AddOperator();    }}</integer></integer></code>
<code class="hljs" php="">/** * 乘法運算符工廠 * Created by jifang on 15/12/7. */public class MultiFactory implements Factory<integer>{    @Override    public Operator<integer>createOperator() {        return new MultiOperator();    }}</integer></integer></code>

    Operator,AddOperatorMultiOperator與上例相同.

    此時, 如果要在靜態工廠中新增加一個開根運算類, 要么需要在createOperator方法中增加一種case, 要么得增加一個createSqrtOper方法, 都是需要修改原來的代碼的. 而在工廠方法中只需要再添加一個SqrtFactory即可:

   

<code class="hljs" php="">/** * 開根運算符 * Created by jifang on 15/12/7. */public class SqrtOperator implements Operator<double>{    @Override    public Double getResult(Double... args) {        if (args != null && args.length >= 1) {            return Math.sqrt(args[0]);        } else {            throw new RuntimeException(Params Number Error  + args.length);        }    }}</double></code>
<code class="hljs" php="">/** * 開根工廠 * Created by jifang on 15/12/7. */public class SqrtFactory implements Factory<double>{    @Override    public Operator<double>createOperator() {        return new SqrtOperator();    }}</double></double></code>

    優點

    基本與靜態工廠模式一致,多的一點優點就是遵循了開放-封閉原則,使得模式的靈活性更強。

    缺點

    與靜態工廠模式差不多, 但是增加了類組織的復雜性;

    小結

    雖然根據理論原則, 需要使用工廠方法模式, 但實際上, 常用的還是靜態工廠模式.


抽象工廠模式

    抽象工廠模式: 提供一個創建一系列相關或相互依賴對象的接口, 而無需指定他們具體的類.

    抽象工廠模式與工廠方法模式的區別:

抽象工廠模式是工廠方法模式的升級版本,他用來創建一組相關或者相互依賴的對象。他與工廠方法模式的區別就在于,工廠方法模式針對的是一個產品等級結構;而抽象工廠模式則是針對的多個產品等級結構. 在編程中,通常一個產品結構,表現為一個接口或者抽象類,也就是說,工廠方法模式提供的所有產品都是衍生自同一個接口或抽象類,而抽象工廠模式所提供的產品則是衍生自不同的接口或抽象類(如下面的Engine, Tyre, Seat).

    在抽象工廠模式中,提出了產品族的概念:所謂的產品族,是指位于不同產品等級結構中功能相關聯的產品組成的家族(如Engine, Tyre, Seat)。抽象工廠模式所提供的一系列產品就組成一個產品族;而工廠方法提供的一系列產品稱為一個等級結構.

    示例:

現在我們要生產兩款車: 高檔(LuxuryCar)與低檔(LowCar), 他們分別配有高端引擎(LuxuryEngine), 高端座椅(LuxurySeat), 高端輪胎(LuxuryTyre)和低端引擎(LowEngine), 低端座椅(LowSeat), 低端輪胎(LowTyre), 下面我們用抽象工廠實現它:

   

    LuxuryCarFactoryLowCarFactory分別代表一類產品族的兩款產品, 類似于數據庫產品族中有MySQL, Oracle, SqlServer

1. 產品

Engine
<code axapta="" class="hljs">public interface Engine {    void start();    void run();}class LowEngine implements Engine {    @Override    public void start() {        System.out.println(啟動慢 ...);    }    @Override    public void run() {        System.out.println(轉速慢 ...);    }}class LuxuryEngine implements Engine {    @Override    public void start() {        System.out.println(啟動快 ...);    }    @Override    public void run() {        System.out.println(轉速快 ...);    }}</code>
Seat
<code axapta="" class="hljs">public interface Seat {    void massage();}class LowSeat implements Seat {    @Override    public void massage() {        System.out.println(不能按摩 ...);    }}class LuxurySeat implements Seat {    @Override    public void massage() {        System.out.println(可提供按摩 ...);    }}</code>
Tyre
<code axapta="" class="hljs">public interface Tyre {    void revolve();}class LowTyre implements Tyre {    @Override    public void revolve() {        System.out.println(旋轉 - 不耐磨 ...);    }}class LuxuryTyre implements Tyre {    @Override    public void revolve() {        System.out.println(旋轉 - 不磨損 ...);    }}</code>

    注意: 其中并沒有車類

2. 產品族Factory

Factory
<code class="hljs" java="">/** * Created by jifang on 15/12/7. */public interface CarFactory {    Engine createEngine();    Seat createSeat();    Tyre createTyre();}</code>
低端車
<code class="hljs" java="">public class LowCarFactory implements CarFactory {    @Override    public Engine createEngine() {        return new LowEngine();    }    @Override    public Seat createSeat() {        return new LowSeat();    }    @Override    public Tyre createTyre() {        return new LowTyre();    }}</code>
高端車
<code class="hljs" java="">public class LuxuryCarFactory implements CarFactory {    @Override    public Engine createEngine() {        return new LuxuryEngine();    }    @Override    public Seat createSeat() {        return new LuxurySeat();    }    @Override    public Tyre createTyre() {        return new LuxuryTyre();    }}</code>

3. Client

<code class="hljs" java="">/** * Created by jifang on 15/12/7. */public class Client {    @Test    public void testLow(){        CarFactory factory = new LowCarFactory();        Engine engine = factory.createEngine();        engine.start();        engine.run();        Seat seat = factory.createSeat();        seat.massage();        Tyre tyre = factory.createTyre();        tyre.revolve();    }    @Test    public void testLuxury(){        CarFactory factory = new LuxuryCarFactory();        Engine engine = factory.createEngine();        engine.start();        engine.run();        Seat seat = factory.createSeat();        seat.massage();        Tyre tyre = factory.createTyre();        tyre.revolve();    }}</code>
優點

    封裝了產品的創建,使得不需要知道具體是哪種產品,只需要知道是哪個工廠就行了,

電腦資料

工廠模式》(http://www.gydabaoji.com)。 可以支持不同類型的產品,使得模式靈活性更強。 可以非常方便的使用一族中間的不同類型的產品。 缺點

    結構太過臃腫,如果產品類型比較多,或者產品族類比較多,就會非常難于管理。 每次如果添加一組產品,那么所有的工廠類都必須添加一個方法,這樣違背了開放-封閉原則。所以一般適用于產品組合產品族變化不大的情況。


使用靜態工廠優化抽象工廠

    由于抽象工廠模式存在結構臃腫以及改動復雜的缺點(比如我們每次需要構造Car, 都需要進行CarFactory factory = new XxxCarFactory();, 而一般一個項目中只會生產一種Car, 如果我們需要更改生產的車的類型, 那么客戶端的每一處調用都需要修改), 因此我們可以使用靜態工廠對其進行改造, 我們使用CarCreator來統一創建一個產品族不同產品, 這樣如果我們的工廠將來更改了產品路線, 改為生產高端車時, 我們僅需改變CAR_TYEP的值就可以了:

<code class="hljs" java="">/** * Created by jifang on 15/12/7. */public class CarCreator {    private static final String CAR_TYPE = low;    private static final String CAR_TYPE_LOW = low;    private static final String CAR_TYPE_LUXURY = luxury;    public static Engine createEngine() {        Engine engine = null;        switch (CAR_TYPE) {            case CAR_TYPE_LOW:                engine = new LowEngine();                break;            case CAR_TYPE_LUXURY:                engine = new LuxuryEngine();                break;        }        return engine;    }    public static Seat createSeat() {        Seat seat = null;        switch (CAR_TYPE) {            case CAR_TYPE_LOW:                seat = new LowSeat();                break;            case CAR_TYPE_LUXURY:                seat = new LuxurySeat();                break;        }        return seat;    }    public static Tyre createTyre() {        Tyre tyre = null;        switch (CAR_TYPE) {            case CAR_TYPE_LOW:                tyre = new LowTyre();                break;            case CAR_TYPE_LUXURY:                tyre = new LuxuryTyre();                break;        }        return tyre;    }}</code>

    其實我們還可以通過反射, 將CarCreator中的switch-case去掉, 而且在實際開發中, 字符串的值我們還可以從配置文件中讀取, 這樣, 如果需要更改產品路線, 我們連程序代碼都懶得改了, 只需要修改配置文件就可以了.

<code class="hljs" java="">/** * Created by jifang on 15/12/7. */public class CarCreatorReflect {    /**     * 在實際開發中, 下面這些常量可以從配置文件中讀取     */    private static final String PACKAGE = com.feiqing.abstractfactory;    private static final String ENGINE = LuxuryEngine;    private static final String TYRE = LuxuryTyre;    private static final String SEAT = LuxurySeat;    public static Engine createEngine() {        String className = PACKAGE + . + ENGINE;        try {            return (Engine) Class.forName(className).newInstance();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        return null;    }    public static Seat createSeat() {        String className = PACKAGE + . + SEAT;        try {            return (Seat) Class.forName(className).newInstance();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        return null;    }    public static Tyre createTyre() {        String className = PACKAGE + . + TYRE;        try {            return (Tyre) Class.forName(className).newInstance();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        return null;    }}</code>

    這樣, 客戶端調起來就清爽多了

<code class="hljs" java="">/** * Created by jifang on 15/12/7. */public class StaticClient {    @Test    public void testLow() {        Engine engine = CarCreator.createEngine();        engine.run();        engine.start();        Seat seat = CarCreator.createSeat();        seat.massage();        Tyre tyre = CarCreator.createTyre();        tyre.revolve();    }    @Test    public void testLuxury() {        Engine engine = CarCreatorReflect.createEngine();        engine.run();        engine.start();        Seat seat = CarCreatorReflect.createSeat();        seat.massage();        Tyre tyre = CarCreatorReflect.createTyre();        tyre.revolve();    }}</code>

小結

分類說明靜態工廠模式用來生成同一等級結構中的任意產品, 對于增加新的產品,需要修改已有代碼工廠方法模式用來生成同一等級結構的固定產品, 支持增加任意產品;抽象工廠模式用來生成不同產品族的全部產品, 對于增加新的產品無能為力;

最新文章
主站蜘蛛池模板: 色达县| 眉山市| 罗田县| 肇源县| 普定县| 巨鹿县| 太保市| 洛隆县| 河源市| 延津县| 海城市| 夹江县| 广灵县| 珠海市| 清河县| 盐津县| 铜山县| 蓝田县| 金乡县| 宣化县| 福鼎市| 延安市| 涞水县| 文安县| 巴彦淖尔市| 株洲市| 兴文县| 瑞丽市| 南岸区| 张家界市| 自贡市| 高要市| 喜德县| 潜江市| 凤山县| 松阳县| 潍坊市| 临漳县| 东方市| 清徐县| 成都市|