設(shè)計(jì)模式之簡(jiǎn)單工廠模式(SimpleFactory)

1.簡(jiǎn)單工廠模式概念

簡(jiǎn)單工廠模式又稱為靜態(tài)工廠方法(Static Factory Method)模式,它屬于類創(chuàng)建型模式(同屬于創(chuàng)建型模式的還有工廠方法模式,抽象工廠模式,單例模式,建造者模式)。在簡(jiǎn)單工廠模式中,可以根據(jù)參數(shù)的不同返回不同類的實(shí)例。簡(jiǎn)單工廠模式專門定義一個(gè)類來(lái)負(fù)責(zé)創(chuàng)建其他類的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類。

2.簡(jiǎn)單工廠模式的結(jié)構(gòu)

這里寫(xiě)圖片描述

由上面的結(jié)構(gòu)圖可以看到,簡(jiǎn)單工廠模式由具體工廠,具體產(chǎn)品,抽象產(chǎn)品三部分組成。
具體工廠(Factory):這個(gè)類是簡(jiǎn)單工廠模式的核心,含有與應(yīng)用緊密相關(guān)的商業(yè)邏輯。工廠類在客戶端的直接調(diào)用下創(chuàng)建產(chǎn)品對(duì)象,它往往由一個(gè)具體Java類實(shí)現(xiàn)。
具體產(chǎn)品(Product):簡(jiǎn)單工廠模式所創(chuàng)建的任何對(duì)象都是這個(gè)類的實(shí)例,具體產(chǎn)品由一個(gè)具體Java類實(shí)現(xiàn)。
抽象產(chǎn)品(AbstractProduct):這個(gè)類是由簡(jiǎn)單工廠模式所創(chuàng)建的對(duì)象的父類,或它們共同擁有的接口。抽象產(chǎn)品可以用一個(gè)Java接口或者Java抽象類實(shí)現(xiàn)。

3.簡(jiǎn)單工廠模式的例子

還是以《大話設(shè)計(jì)模式》中小菜做的計(jì)算器為例,在這個(gè)例子中計(jì)算器擁有加減乘除這四個(gè)操作,其實(shí)就可以使用簡(jiǎn)單工廠設(shè)計(jì)模式來(lái)設(shè)計(jì)這個(gè)計(jì)算器,首先看這個(gè)例子的結(jié)構(gòu)圖:


這里寫(xiě)圖片描述

  在這個(gè)例子當(dāng)中,其實(shí)運(yùn)算類就充當(dāng)了抽象產(chǎn)品類(AbstractProduct),加減乘除這個(gè)四個(gè)具體的運(yùn)算類實(shí)際上就是具體產(chǎn)品類(Product),而簡(jiǎn)單工廠類就是在客戶端下創(chuàng)建具體的運(yùn)算來(lái)完成相應(yīng)的操作。
  
運(yùn)算類(Operation):

package com.jxs.simpleFactory;

/**
 * Created by jiangxs on 2018/5/2.
 */
public abstract class Operation {

    private double numberA = 0.0;
    private double numberB = 0.0;

    public double getNumberA() {
        return numberA;
    }

    public void setNumberA(double numberA) {
        this.numberA = numberA;
    }

    public double getNumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }

    public abstract double getResult();
}

工廠類(OperationFactory):

package com.jxs.simpleFactory;

/**
 * Created by jiangxs on 2018/5/2.
 */
public class OperationFactory {

    public static Operation createOperation(char operator) {

        Operation operation = null;
        switch (operator) {

            case '+':
                operation = new OperationAdd();
                break;
            case '-':
                operation = new OperationSub();
                break;
            case '*':
                operation = new OperationMul();
                break;
            case '/':
                operation = new OperationDiv();
                break;
            default:
                throw new RuntimeException("傳入的運(yùn)算符不支持!");
        }
        return operation;
    }
}

加法類(OperationAdd):

package com.jxs.simpleFactory;

/**
 * Created by jiangxs on 2018/5/2.
 */
public class OperationAdd extends Operation {

    @Override
    public double getResult() {

        return getNumberA()+getNumberB();
    }
}

減法類(OperationSub):

package com.jxs.simpleFactory;

/**
 * Created by jiangxs on 2018/5/2.
 */
public class OperationSub extends Operation {

    @Override
    public double getResult() {

        return getNumberA() - getNumberB();
    }
}

乘法類(OperationMul):

package com.jxs.simpleFactory;

/**
 * Created by jiangxs on 2018/5/2.
 */
public class OperationMul extends Operation {

    @Override
    public double getResult() {

        return getNumberA() * getNumberB();
    }
}

除法類(OperationDiv):

package com.jxs.simpleFactory;

/**
 * Created by jiangxs on 2018/5/2.
 */
public class OperationDiv extends Operation {

    @Override
    public double getResult() {

        return getNumberA() / getNumberB();
    }
}

客戶端代碼:

package com.jxs.simpleFactory;

/**
 * Created by jiangxs on 2018/5/2.
 */
public class OperationResult {

    public static void main(String[] args) {

        Operation operation = null;
        char operator;

        operator = '/';
        double numberA = 10.0;
        double numberB = 20.0;
        operation = OperationFactory.createOperation(operator);
        operation.setNumberA(numberA);
        operation.setNumberB(numberB);
        System.out.println(operation.getResult());
    }
}

運(yùn)行結(jié)果:

0.5

Process finished with exit code 0

4.簡(jiǎn)單工廠模式的總結(jié)

(1)簡(jiǎn)單工廠模式的優(yōu)點(diǎn)

  • 工廠類含有必要的判斷邏輯,可以決定在什么時(shí)候創(chuàng)建哪一個(gè)產(chǎn)品類的實(shí)例,客戶端可以免除直接創(chuàng)建產(chǎn)品對(duì)象的責(zé)任,而僅僅“消費(fèi)”產(chǎn)品;簡(jiǎn)單工廠模式通過(guò)這種做法實(shí)現(xiàn)了對(duì)責(zé)任的分割,它提供了專門的工廠類用于創(chuàng)建對(duì)象。
  • 客戶端無(wú)須知道所創(chuàng)建的具體產(chǎn)品類的類名,只需要知道具體產(chǎn)品類所對(duì)應(yīng)的參數(shù)即可,對(duì)于一些復(fù)雜的類名,通過(guò)簡(jiǎn)單工廠模式可以減少使用者的記憶量。

(2)簡(jiǎn)單工廠模式的缺點(diǎn)

  • 由于工廠類集中了所有產(chǎn)品創(chuàng)建邏輯,工廠類一般被我們稱作“全能類”或者“上帝類”,因?yàn)樗械漠a(chǎn)品創(chuàng)建他都能完成,一旦其不能正常工作,整個(gè)系統(tǒng)都要受到影響。
  • 使用簡(jiǎn)單工廠模式將會(huì)增加系統(tǒng)中類的個(gè)數(shù),在一定程序上增加了系統(tǒng)的復(fù)雜度和理解難度。
  • 系統(tǒng)擴(kuò)展困難,一旦添加新產(chǎn)品就不得不修改工廠邏輯,在產(chǎn)品類型較多時(shí),有可能造成工廠邏輯過(guò)于復(fù)雜,不利于系統(tǒng)的擴(kuò)展和維護(hù)。所以說(shuō)從工廠的角度來(lái)說(shuō)簡(jiǎn)單工廠模式是不符合“開(kāi)-閉”原則的。
  • 簡(jiǎn)單工廠模式由于使用了靜態(tài)工廠方法,造成工廠角色無(wú)法形成基于繼承的等級(jí)結(jié)構(gòu)。

(3)簡(jiǎn)單工廠模式的適用場(chǎng)景

  • 工廠類負(fù)責(zé)創(chuàng)建的對(duì)象比較少:由于創(chuàng)建的對(duì)象較少,不會(huì)造成工廠方法中的業(yè)務(wù)邏輯太過(guò)復(fù)雜。
  • 客戶端只知道傳入工廠類的參數(shù),對(duì)于如何創(chuàng)建對(duì)象不關(guān)心:客戶端既不需要關(guān)心創(chuàng)建細(xì)節(jié),甚至連類名都不需要記住,只需要知道類型所對(duì)應(yīng)的參數(shù)。

注:
以上代碼均可在github上進(jìn)行下載:https://github.com/xsongj/designPattern

參考:
《大話數(shù)據(jù)結(jié)構(gòu)》
https://blog.csdn.net/xingjiarong/article/details/49999121

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

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