久久99热66热这里只有精品,特黄特色的大片在线观看,亚洲日本三级在线观看,国产三级农村妇女在线,亚洲av毛片免费在线观看,哺乳叫自慰在线看,天天干美女av网

工廠模式 -電腦資料

電腦資料 時(shí)間:2019-01-01 我要投稿
【www.dameics.com - 電腦資料】

   

工廠模式
    標(biāo)簽: Java與設(shè)計(jì)模式


    工廠模式

    用工廠方法代替了new操作, 將選擇實(shí)現(xiàn)類,創(chuàng)建對(duì)象統(tǒng)一管理和控制.從而將調(diào)用者(Client)與實(shí)現(xiàn)類進(jìn)行解耦.實(shí)現(xiàn)了創(chuàng)建者與調(diào)用者分離;

使用場(chǎng)景

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


靜態(tài)工廠模式

    靜態(tài)工廠模式是工廠模式中最簡(jiǎn)單的一種,他可以用比較簡(jiǎn)單的方式隱藏創(chuàng)建對(duì)象的細(xì)節(jié),一般只需要告訴工廠類所需要的類型,工廠類就會(huì)返回需要的產(chǎn)品類,而客戶端看到的也只是產(chǎn)品的抽象對(duì)象(interface),因此無(wú)需關(guān)心到底是返回了哪個(gè)子類

    我們以運(yùn)算符類為例, 解釋靜態(tài)工廠模式.

   

    Operator接口

<code class="hljs" scala="">/** * 運(yùn)算符接口 * Created by jifang on 15/12/7. */public interface Operator<t>{    T getResult(T... args);}</t></code>
實(shí)現(xiàn)類
<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="">/** * 靜態(tài)工廠(注: 只返回產(chǎn)品的抽象[即接口]) * 包含兩種實(shí)現(xiàn)策略 * 1. 根據(jù)傳入的operator名進(jìn)行實(shí)例化對(duì)象 * 2. 直接調(diào)用相應(yīng)的構(gòu)造實(shí)例的方法 * 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;    }    /* ** 第二種實(shí)現(xiàn)策略 ** */    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>

    優(yōu)點(diǎn)

隱藏了對(duì)象創(chuàng)建的細(xì)節(jié),將產(chǎn)品的實(shí)例化過(guò)程放到了工廠中實(shí)現(xiàn),

工廠模式

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

    缺點(diǎn)

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

工廠方法模式

    由于靜態(tài)工廠方法模式不滿足OCP, 因此就出現(xiàn)了工廠方法模式; 工廠方法模式和靜態(tài)工廠模式最大的不同在于:靜態(tài)工廠模式只有一個(gè)(對(duì)于一個(gè)項(xiàng)目/獨(dú)立模塊)只有一個(gè)工廠類, 而工廠方法模式則有一組實(shí)現(xiàn)了相同接口的工廠類.

   

工廠
<code class="hljs" scala="">/** * Created by jifang on 15/12/7. */public interface Factory<t>{    Operator<t>createOperator();}</t></t></code>
工廠實(shí)現(xiàn)
<code class="hljs" php="">/** * 加法運(yùn)算符工廠 * 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="">/** * 乘法運(yùn)算符工廠 * 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與上例相同.

    此時(shí), 如果要在靜態(tài)工廠中新增加一個(gè)開根運(yùn)算類, 要么需要在createOperator方法中增加一種case, 要么得增加一個(gè)createSqrtOper方法, 都是需要修改原來(lái)的代碼的. 而在工廠方法中只需要再添加一個(gè)SqrtFactory即可:

   

<code class="hljs" php="">/** * 開根運(yùn)算符 * 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>

    優(yōu)點(diǎn)

    基本與靜態(tài)工廠模式一致,多的一點(diǎn)優(yōu)點(diǎn)就是遵循了開放-封閉原則,使得模式的靈活性更強(qiáng)。

    缺點(diǎn)

    與靜態(tài)工廠模式差不多, 但是增加了類組織的復(fù)雜性;

    小結(jié)

    雖然根據(jù)理論原則, 需要使用工廠方法模式, 但實(shí)際上, 常用的還是靜態(tài)工廠模式.


抽象工廠模式

    抽象工廠模式: 提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口, 而無(wú)需指定他們具體的類.

    抽象工廠模式與工廠方法模式的區(qū)別:

抽象工廠模式是工廠方法模式的升級(jí)版本,他用來(lái)創(chuàng)建一組相關(guān)或者相互依賴的對(duì)象。他與工廠方法模式的區(qū)別就在于,工廠方法模式針對(duì)的是一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu);而抽象工廠模式則是針對(duì)的多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu). 在編程中,通常一個(gè)產(chǎn)品結(jié)構(gòu),表現(xiàn)為一個(gè)接口或者抽象類,也就是說(shuō),工廠方法模式提供的所有產(chǎn)品都是衍生自同一個(gè)接口或抽象類,而抽象工廠模式所提供的產(chǎn)品則是衍生自不同的接口或抽象類(如下面的Engine, Tyre, Seat).

    在抽象工廠模式中,提出了產(chǎn)品族的概念:所謂的產(chǎn)品族,是指位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中功能相關(guān)聯(lián)的產(chǎn)品組成的家族(如Engine, Tyre, Seat)。抽象工廠模式所提供的一系列產(chǎn)品就組成一個(gè)產(chǎn)品族;而工廠方法提供的一系列產(chǎn)品稱為一個(gè)等級(jí)結(jié)構(gòu).

    示例:

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

   

    LuxuryCarFactoryLowCarFactory分別代表一類產(chǎn)品族的兩款產(chǎn)品, 類似于數(shù)據(jù)庫(kù)產(chǎn)品族中有MySQL, Oracle, SqlServer

1. 產(chǎn)品

Engine
<code axapta="" class="hljs">public interface Engine {    void start();    void run();}class LowEngine implements Engine {    @Override    public void start() {        System.out.println(啟動(dòng)慢 ...);    }    @Override    public void run() {        System.out.println(轉(zhuǎn)速慢 ...);    }}class LuxuryEngine implements Engine {    @Override    public void start() {        System.out.println(啟動(dòng)快 ...);    }    @Override    public void run() {        System.out.println(轉(zhuǎn)速快 ...);    }}</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(旋轉(zhuǎn) - 不耐磨 ...);    }}class LuxuryTyre implements Tyre {    @Override    public void revolve() {        System.out.println(旋轉(zhuǎn) - 不磨損 ...);    }}</code>

    注意: 其中并沒(méi)有車類

2. 產(chǎn)品族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>
優(yōu)點(diǎn)

    封裝了產(chǎn)品的創(chuàng)建,使得不需要知道具體是哪種產(chǎn)品,只需要知道是哪個(gè)工廠就行了,

電腦資料

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

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


使用靜態(tài)工廠優(yōu)化抽象工廠

    由于抽象工廠模式存在結(jié)構(gòu)臃腫以及改動(dòng)復(fù)雜的缺點(diǎn)(比如我們每次需要構(gòu)造Car, 都需要進(jìn)行CarFactory factory = new XxxCarFactory();, 而一般一個(gè)項(xiàng)目中只會(huì)生產(chǎn)一種Car, 如果我們需要更改生產(chǎn)的車的類型, 那么客戶端的每一處調(diào)用都需要修改), 因此我們可以使用靜態(tài)工廠對(duì)其進(jìn)行改造, 我們使用CarCreator來(lái)統(tǒng)一創(chuàng)建一個(gè)產(chǎn)品族不同產(chǎn)品, 這樣如果我們的工廠將來(lái)更改了產(chǎn)品路線, 改為生產(chǎn)高端車時(shí), 我們僅需改變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>

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

<code class="hljs" java="">/** * Created by jifang on 15/12/7. */public class CarCreatorReflect {    /**     * 在實(shí)際開發(fā)中, 下面這些常量可以從配置文件中讀取     */    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>

    這樣, 客戶端調(diào)起來(lái)就清爽多了

<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>

小結(jié)

分類說(shuō)明靜態(tài)工廠模式用來(lái)生成同一等級(jí)結(jié)構(gòu)中的任意產(chǎn)品, 對(duì)于增加新的產(chǎn)品,需要修改已有代碼工廠方法模式用來(lái)生成同一等級(jí)結(jié)構(gòu)的固定產(chǎn)品, 支持增加任意產(chǎn)品;抽象工廠模式用來(lái)生成不同產(chǎn)品族的全部產(chǎn)品, 對(duì)于增加新的產(chǎn)品無(wú)能為力;

最新文章