工廠模式和策略模式

為什么將這兩個(gè)模式一起說(shuō)呢,因?yàn)樗鼈兘?jīng)常是同時(shí)出現(xiàn)(框架中)或者使用(自己寫的代碼).
直接上代碼,然后再說(shuō)其中的區(qū)別。

工廠模式(這里主要以抽象工廠為例)

意圖:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無(wú)需指定它們具體的類。
書內(nèi)完整:是一種為訪問類提供一個(gè)創(chuàng)建一組相關(guān)或相互依賴對(duì)象的接口,且訪問類無(wú)須指定所要產(chǎn)品的具體類就能得到同族的不同等級(jí)的產(chǎn)品的模式結(jié)構(gòu)。
主要解決:主要解決接口選擇的問題。

何時(shí)使用:系統(tǒng)的產(chǎn)品有多于一個(gè)的產(chǎn)品族,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品。

如何解決:在一個(gè)產(chǎn)品族里面,定義多個(gè)產(chǎn)品。

關(guān)鍵代碼:在一個(gè)工廠里聚合多個(gè)同類產(chǎn)品。

應(yīng)用實(shí)例:工作了,為了參加一些聚會(huì),肯定有兩套或多套衣服吧,比如說(shuō)有商務(wù)裝(成套,一系列具體產(chǎn)品)、時(shí)尚裝(成套,一系列具體產(chǎn)品),甚至對(duì)于一個(gè)家庭來(lái)說(shuō),可能有商務(wù)女裝、商務(wù)男裝、時(shí)尚女裝、時(shí)尚男裝,這些也都是成套的,即一系列具體產(chǎn)品。假設(shè)一種情況(現(xiàn)實(shí)中是不存在的,要不然,沒法進(jìn)入共產(chǎn)主義了,但有利于說(shuō)明抽象工廠模式),在您的家中,某一個(gè)衣柜(具體工廠)只能存放某一種這樣的衣服(成套,一系列具體產(chǎn)品),每次拿這種成套的衣服時(shí)也自然要從這個(gè)衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具體工廠)都是衣柜類的(抽象工廠)某一個(gè),而每一件成套的衣服又包括具體的上衣(某一具體產(chǎn)品),褲子(某一具體產(chǎn)品),這些具體的上衣其實(shí)也都是上衣(抽象產(chǎn)品),具體的褲子也都是褲子(另一個(gè)抽象產(chǎn)品)。

優(yōu)點(diǎn):
抽象工廠模式除了具有工廠方法模式的優(yōu)點(diǎn)外,其他主要優(yōu)點(diǎn)如下。
1.可以在類的內(nèi)部對(duì)產(chǎn)品族中相關(guān)聯(lián)的多等級(jí)產(chǎn)品共同管理,而不必專門引入多個(gè)新的類來(lái)進(jìn)行管理。
2.當(dāng)需要產(chǎn)品族時(shí),抽象工廠可以保證客戶端始終只使用同一個(gè)產(chǎn)品的產(chǎn)品組。
3.抽象工廠增強(qiáng)了程序的可擴(kuò)展性,當(dāng)增加一個(gè)新的產(chǎn)品族時(shí),不需要修改原代碼,滿足開閉原則。
4.當(dāng)一個(gè)產(chǎn)品族中的多個(gè)對(duì)象被設(shè)計(jì)成一起工作時(shí),它能保證客戶端始終只使用同一個(gè)產(chǎn)品族中的對(duì)象。
缺點(diǎn):
1.產(chǎn)品族擴(kuò)展非常困難,要增加一個(gè)系列的某一產(chǎn)品,既要在抽象的 Creator 里加代碼,又要在具體的里面加代碼。
2.當(dāng)產(chǎn)品族中需要增加一個(gè)新的產(chǎn)品時(shí),所有的工廠類都需要進(jìn)行修改。增加了系統(tǒng)的抽象性和理解難度。
使用場(chǎng)景: 1、QQ 換皮膚,一整套一起換。 2、生成不同操作系統(tǒng)的程序。

注意事項(xiàng):產(chǎn)品族難擴(kuò)展,產(chǎn)品等級(jí)易擴(kuò)展。

先看基本目錄哈
截屏2022-07-05 下午8.13.14.png
截屏2022-07-05 下午8.12.26.png

截屏2022-07-05 下午8.13.44.png
1.先創(chuàng)建Shape和Color工廠

Color.java

public interface Color {
    /**
     * 填充
     */
    void fill();
}

Shape.jaba

public interface Shape {

    /**
     * 繪畫
     */
    void draw();
}
2.然后我們color和shape都拿其中一個(gè)來(lái)舉例,其他效仿哈

Red.java

public class Red implements Color {

    @Override
    public void fill() {
        System.out.println("Inside Red::fill() method.");
    }
}

Circle.java

public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }
}
3.再創(chuàng)建工廠創(chuàng)造器

FactoryProducer

public class FactoryProducer  {
    public static AbstractFactoryDemo getFactory(String choice) {
        if (choice.equalsIgnoreCase("SHAPE")) return new ShapeFactory();
        if (choice.equalsIgnoreCase("COLOR")) return new ColorFactory();
        return null;
    }
}
4.最后測(cè)試一下(自己創(chuàng)一個(gè)類)
public static void main(String[] args) {
      //獲取圖形工廠
      AbstractFactoryDemo shape = FactoryProducer.getFactory("SHAPE");
      //通過(guò)圖形工廠 獲取圖形中的3個(gè)或多個(gè)圖形
      Shape circle = shape.getShape("CIRCLE");
      circle.draw();
      Shape rectangle = shape.getShape("RECTANGLE");
      rectangle.draw();
      Shape square = shape.getShape("SQUARE");
      square.draw();

      //獲取顏色工廠
      AbstractFactoryDemo color = FactoryProducer.getFactory("COLOR");
      //通過(guò)顏色工廠 獲取顏色中的3個(gè)或多個(gè)顏色
      Color red = color.getColor("RED");
      red.fill();
      Color yellow = color.getColor("YELLOW");
      yellow.fill();
      Color blue = color.getColor("BLUE");
      blue.fill();
  }
輸出結(jié)果:
截屏2022-07-05 下午8.18.39.png

策略模式

意圖:定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái), 并且使它們可相互替換。
書內(nèi)完整:該模式定義了一系列算法,并將每個(gè)算法封裝起來(lái),使它們可以相互替換,且算法的變化不會(huì)影響使用算法的客戶。策略模式屬于對(duì)象行為模式,它通過(guò)對(duì)算法進(jìn)行封裝,把使用算法的責(zé)任和算法的實(shí)現(xiàn)分割開來(lái),并委派給不同的對(duì)象對(duì)這些算法進(jìn)行管理。
主要解決:在有多種算法相似的情況下,使用 if...else 所帶來(lái)的復(fù)雜和難以維護(hù)。

何時(shí)使用:一個(gè)系統(tǒng)有許多許多類,而區(qū)分它們的只是他們直接的行為。

如何解決:將這些算法封裝成一個(gè)一個(gè)的類,任意地替換。

關(guān)鍵代碼:實(shí)現(xiàn)同一個(gè)接口。

應(yīng)用實(shí)例: 1、JAVA AWT 中的 LayoutManager 2、旅行的出游方式,選擇騎自行車、坐汽車,每一種旅行方式都是一個(gè)策略。3、spring中使用。 4、jdk中使用。 5、電商的多促銷模式。 6、多種不同的支付方式。

優(yōu)點(diǎn):
1.算法可以自由切換。 1.2、避免使用多重條件判斷。 1.3、擴(kuò)展性良好。
2.多重條件語(yǔ)句不易維護(hù),而使用策略模式可以避免使用多重條件語(yǔ)句,如 if...else 語(yǔ)句、switch...case 語(yǔ)句。
3.策略模式提供了一系列的可供重用的算法族,恰當(dāng)使用繼承可以把算法族的公共代碼轉(zhuǎn)移到父類里面,從而避免重復(fù)的代碼。
4.策略模式可以提供相同行為的不同實(shí)現(xiàn),客戶可以根據(jù)不同時(shí)間或空間要求選擇不同的。
5.策略模式提供了對(duì)開閉原則的完美支持,可以在不修改原代碼的情況下,靈活增加新算法。
6.策略模式把算法的使用放到環(huán)境類中,而算法的實(shí)現(xiàn)移到具體策略類中,實(shí)現(xiàn)了二者的分離。
缺點(diǎn): 1.策略類會(huì)增多。 2.所有策略類都需要對(duì)外暴露。
3.客戶端必須理解所有策略算法的區(qū)別,以便適時(shí)選擇恰當(dāng)?shù)乃惴悺?br> 4.策略模式造成很多的策略類,增加維護(hù)難度。

使用場(chǎng)景: 1、如果在一個(gè)系統(tǒng)里面有許多類,它們之間的區(qū)別僅在于它們的行為,那么使用策略模式可以動(dòng)態(tài)地讓一個(gè)對(duì)象在許多行為中選擇一種行為。 2、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種。 3、如果一個(gè)對(duì)象有很多的行為,如果不用恰當(dāng)?shù)哪J?,這些行為就只好使用多重的條件選擇語(yǔ)句來(lái)實(shí)現(xiàn)。

注意事項(xiàng):如果一個(gè)系統(tǒng)的策略多于四個(gè),就需要考慮使用混合模式,解決策略類膨脹的問題。

大致的目錄跟工廠模式一樣差不多創(chuàng)建即可

CrabCookingStrategy 、CrabCooking(抽象策略接口)、(具體策略)1.BraisedCrabs 2.SteamedCrabs、Kitchen(環(huán)境)
為了方便看我直接放一個(gè)類了

public class CrabCookingStrategy {
    private Kitchen kitchen;    //廚房
    private CrabCooking qzx, hsx;    //大閘蟹加工者  
    CrabCookingStrategy() {
        System.out.println("策略模式在大閘蟹做菜中的應(yīng)用");
        List arrayList= new ArrayList<>();
        //環(huán)境
        kitchen = new Kitchen();
        // 清蒸
        qzx = new SteamedCrabs();
        // 紅燒
        hsx = new BraisedCrabs();

        //修改策略
        itemStateChanged(qzx);
        System.out.println(kitchen.getStrategy());
        itemStateChanged(hsx);
        System.out.println(kitchen.getStrategy());
        itemStateChanged(qzx);
        System.out.println(kitchen.getStrategy());
    }
    public void itemStateChanged(Object action) {
        if (action == qzx) {
            kitchen.setStrategy(qzx);
            kitchen.cookingMethod(); //清蒸
        } else if (action == hsx) {
            kitchen.setStrategy(hsx);
            kitchen.cookingMethod(); //紅燒
        }
    }
    public static void main(String[] args) {
        new CrabCookingStrategy();
    }
}
//抽象策略類:大閘蟹加工類
interface CrabCooking {
    public void cookingMethod();    //做菜方法
}
//具體策略類:清蒸大閘蟹
class SteamedCrabs implements CrabCooking {
    private static final long serialVersionUID = 1L;
    public void cookingMethod() {
    System.out.println("清蒸大閘蟹");
    }
}
//具體策略類:紅燒大閘蟹
class BraisedCrabs implements CrabCooking {
    private static final long serialVersionUID = 1L;
    public void cookingMethod() {
        System.out.println("紅燒大閘蟹");
    }
}
//環(huán)境類:廚房
class Kitchen {

    //抽象策略
    private CrabCooking strategy;
    public void setStrategy(CrabCooking strategy) {
        this.strategy = strategy;
    }
    public CrabCooking getStrategy() {
        return strategy;
    }
    public void cookingMethod() {
        System.out.println("做菜");
        strategy.cookingMethod();    //做菜
    }
}
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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