java23種設計模式——3、工廠模式

源碼在個人githubgitee中獲取html

目錄

java23種設計模式—— 1、設計模式介紹
java23種設計模式—— 2、單例模式
java23種設計模式——3、工廠模式
java23種設計模式——4、原型模式
java23種設計模式——5、建造者模式
java23種設計模式——6、適配器模式java

工廠模式

工廠模式介紹

工廠模式是咱們最經常使用的實例化對象模式了,是用工廠方法代替new操做的一種模式。著名的Jive論壇 ,就大量使用了工廠模式,工廠模式在Java程序系統能夠說是隨處可見。由於工廠模式就至關於建立實例對象的new,咱們常常要根據類Class生成實例對象,如A a=new A() 工廠模式也是用來建立實例對象的,因此之後new時就要多個心眼,是否能夠考慮使用工廠模式,雖然這樣作,可能多作一些工做,但會給你係統帶來更大的可擴展性和儘可能少的修改量。(百度百科)
工廠模式又分爲:git

  • 簡單工廠模式:容許接口建立對象,但不會暴露對象的建立邏輯。
  • 工廠方法模式: 容許接口建立對象,但使用哪一個類來建立對象,則是交由子類決定的
  • 抽象方法模式: 抽象工廠是一個可以建立一系列相關的對象而無需指定/公開其具體類的接口。該模式可以提供其餘工廠的對象,在其內部建立其餘對象。

簡單工廠模式

屬於建立型模式,又叫作靜態工廠方法模式,不屬於23種GOF設計模式之一。是由一個工廠對象決定建立出哪種產品類的實例。違背「開放 - 關閉原則」,一旦添加新產品就不得不修改工廠類的邏輯,這樣就會形成工廠邏輯過於複雜。github

假設如今有一家餐館設計模式

public interface Restaurant {
   public void cook();
}

餐館有兩種菜品:紅燒肉和雞蛋羹bash

//雞蛋羹
public class Egg implements Restaurant {
    @Override
    public void cook() {
        System.out.println("雞蛋羹作好了");
    }
}
//紅燒肉
public class Meet implements Restaurant{
    @Override
    public void cook() {
        System.out.println("紅燒肉作好了");
    }
}

餐館裏有服務員,來負責向後廚傳達客人的需求iphone

public class Waiter {
	//一樣能夠定義常量而後經過switch語句來實現
    public static Restaurant getFood(String orderType) {
        Restaurant restaurant = null;
        if(orderType.equals("紅燒肉")){
            restaurant = new Meet();
        }else if (orderType.equals("雞蛋羹")){
            restaurant = new Egg();
        }
        return restaurant;
    }
}

如今顧客來了,要點一份紅燒肉,就只須要和服務員說就行ide

public class Customer {
    public static void main(String[] args) {
        Restaurant restaurant = Waiter.getFood("紅燒肉");
        restaurant.cook();
    }
}

輸出測試

紅燒肉作好了

經過以上方法,的確實現了 提供建立實例的功能,而無需關心具體實現。可是咱們不難發現,這種方法的擴展性不好,若是餐館新出了一款菜品,還須要咱們在服務員方法裏修改。這使得當餐館的菜品不少時,工廠方法代碼邏輯將會很是複雜優化

工廠方法模式

工廠方法模式,又稱工廠模式、多態工廠模式和虛擬構造器模式,經過定義工廠父類負責定義建立對象的公共接口,而子類則負責生成具體的對象。是在工廠模式家族中是用的最多模式,通常項目中存在最多的就是這個模式。是對簡單工廠模式的一個優化,讓每一個對象都有一個與之對應的工廠。

這裏咱們接着用上面的例子,假設這家餐廳的生意很是好,因此餐館的老闆把餐館全部負責點餐的服務員都辭退了,取而代之的是添加了一個收銀臺,而後讓每一個廚師只負責作同樣菜。這樣客人只須要和收銀臺說要求就好了。

這裏咱們接着用上面的類。除去服務員Waiter類

新建Cashier接口

/**
 * @author codermy
 * @createTime 2020/6/15
 */
public interface Cashier {
    public Restaurant getFood();
}

而後給每個菜品新建一個工廠類

EggCooker

/**
 * @author codermy
 * @createTime 2020/6/15
 */
public class EggCooker implements Cashier {
    @Override
    public Restaurant getFood() {
        return new Egg();
    }
}

MeetCooker

/**
 * @author codermy
 * @createTime 2020/6/15
 */
public class MeetCooker implements Cashier{
    @Override
    public Restaurant getFood() {
        return new Meet();
    }
}

而後顧客點單隻須要在收銀臺,餐廳的系統會自動將信息傳遞給相應的廚師,對應的廚師就能在餐館中把菜作好

/**
 * @author codermy
 * @createTime 2020/6/15
 * 消費者
 */
public class Customer {
    public static void main(String[] args) {
        Cashier order = new EggCooker();
        Restaurant food = order.getFood();
        food.cook();
    }
}

輸出結果

雞蛋羹作好了

工廠方法模式解決了簡單工廠模式不符合的開閉原則,當添加一個菜品時,只須要再僱傭一個廚師就行(從現實角度看,老闆有點虧哦)。可是這也增長了系統的複雜度(菜越多,廚師就越多,這哪家餐館頂的住)

抽象工廠模式

這個模式解決了每一個工廠只能建立一類產品(工廠方法模式)的問題

這裏用餐館的例子不太形象,不是很容易理解,強行舉例可能會和上面的方法弄混,我本身繞了好一會,因此咱們換一個例子。

如今咱們人手不離手機,咱們假設手機有以下幾個功能

//手機產品接口
public interface IphoneProduct {
    void callup();//打電話
    void sendSms();//發短信
}

每一個人家裏又都有路由器,路由器有以下功能

//路由器產品接口
public interface IRouterProduct {
    void openwifi();//開啓wifi
    void setting();//設置wifi
}

而後如今有一個抽象產品工廠,是來生產這兩樣產品的,假設生產手機和路由器的方法是同樣的,只是須要加上廠商信息

//抽象產品工廠
public interface IProductFactory {
    //生產手機
    IphoneProduct iphoneProduct();
    //生產路由器
    IRouterProduct iRouterProduct();
}

如今有兩家廠商,小米和華爲工廠,能夠生產手機和路由器,他們兩家廠商分別由兩條產業線來作手機和路由器

//小米手機
public class XiaomiPhone implements IphoneProduct{

    @Override
    public void callup() {
        System.out.println("用小米手機打電話");
    }

    @Override
    public void sendSms() {
        System.out.println("用小米手機發短信");
    }
}
//小米路由器
public class XiaomiRouter implements IRouterProduct {

    @Override
    public void openwifi() {
        System.out.println("打開小米wifi");
    }

    @Override
    public void setting() {
        System.out.println("設置小米wifi");
    }
}
//小米廠商
public class XiaomiFactory implements IProductFactory {
    @Override
    public IphoneProduct iphoneProduct() {
        return new XiaomiPhone();
    }

    @Override
    public IRouterProduct iRouterProduct() {
        return new XiaomiRouter();
    }
}
//華爲手機
public class HuaweiPhone implements IphoneProduct {

    @Override
    public void callup() {
        System.out.println("用華爲手機打電話");
    }

    @Override
    public void sendSms() {
        System.out.println("用華爲手機發短信");
    }
}
//華爲路由器
    public class HuaweiRouter implements IRouterProduct {

        @Override
        public void openwifi() {
            System.out.println("打開華爲wifi");
        }

        @Override
        public void setting() {
            System.out.println("設置華爲wifi");
        }
    }
//華爲工廠
public class HuaweiFactory implements IProductFactory {
    @Override
    public IphoneProduct iphoneProduct() {
        return new HuaweiPhone();
    }

    @Override
    public IRouterProduct iRouterProduct() {
        return new HuaweiRouter();
    }
}

消費者類

//消費者/測試類
public class Customer {
    public static void main(String[] args) {

        System.out.println("==============小米產品=================");
        XiaomiFactory xiaomiFactory = new XiaomiFactory();//新建一個小米工廠
        IphoneProduct xiaomiiphoneProduct = xiaomiFactory.iphoneProduct();//小米工廠開始生產小米手機
        xiaomiiphoneProduct.callup();//測試小米手機打電話功能
        IRouterProduct xiaomiiRouterProduct = xiaomiFactory.iRouterProduct();//小米工廠開始生產小米路由器
        xiaomiiRouterProduct.openwifi();//測試小米路由器打開wifi功能

        System.out.println("==============華爲產品=================");
        HuaweiFactory huaweiFactory = new HuaweiFactory();

        IphoneProduct huaweiiphoneProduct1 = huaweiFactory.iphoneProduct();
        huaweiiphoneProduct1.callup();
        IRouterProduct huaweiiRouterProduct = huaweiFactory.iRouterProduct();
        huaweiiRouterProduct.openwifi();
    }
}

輸出

==============小米產品=================
用小米手機打電話
打開小米wifi
==============華爲產品=================
用華爲手機打電話
打開華爲wifi

抽象工廠模式相較於以上兩種模式難以理解一些。這裏提供另外一種寫法比較好理解,來自Guide哥的博客(如下全部內容)

不知道你們玩過穿越火線或者吃雞這類遊戲了嗎,遊戲中存在各類槍。咱們假設如今存在AK、M4A1兩類槍,每一種槍對應一種子彈。咱們如今這樣考慮生產AK的工廠能夠順便生產AK使用的子彈,生產M4A1的工廠能夠順便生產M4A1使用的子彈。(AK工廠生產AK系列產品包括子彈啊,AK槍的類型啊這些,M4A1工廠同理)
————————————————

(1)建立相關接口:

public interface Gun {
    public void shooting();
}

子彈

public interface Bullet {
    public void load();
}

(2)建立接口對應實現類:

AK類

public class AK implements Gun{

    @Override
    public void shooting() {
        System.out.println("shooting with AK");

    }

}

M4A1類

public class M4A1 implements Gun {

    @Override
    public void shooting() {
        System.out.println("shooting with M4A1");

    }

}

AK子彈類

public class AK_Bullet implements Bullet {

    @Override
    public void load() {
        System.out.println("Load bullets with AK");
    }

}

M4A1子彈類

public class M4A1_Bullet implements Bullet {

    @Override
    public void load() {
        System.out.println("Load bullets with M4A1");
    }

}

(3)建立工廠接口

public interface Factory {
    public Gun produceGun();
    public Bullet produceBullet();
}

(4)建立具體工廠

生產AK和AK子彈的工廠

public class AK_Factory implements Factory{

    @Override
    public Gun produceGun() {
        return new AK();
    }

    @Override
    public Bullet produceBullet() {
        return new AK_Bullet();
    }

}

生產M4A1和M4A1子彈的工廠

public class M4A1_Factory implements Factory{

    @Override
    public Gun produceGun() {
        return new M4A1();
    }

    @Override
    public Bullet produceBullet() {
        return new M4A1_Bullet();
    }

}

(5)測試

public class Test {

    public static void main(String[] args) {  

     Factory factory;
     Gun gun;
     Bullet bullet;

     factory =new AK_Factory();
     bullet=factory.produceBullet();
     bullet.load();
     gun=factory.produceGun();
     gun.shooting(); 

    }

}

輸出結果:

Load bullets with AK
shooting with AK
相關文章
相關標籤/搜索