1. 程式人生 > >程式設計設計模式 -- (工廠設計)

程式設計設計模式 -- (工廠設計)

一 、工廠設計模式

需求 : 舉辦晚會.

開始 : 晚會開始了…
節目1 : 劉德華演唱 <冰雨> 歌曲 …
節目2 : 少女時代跳 <Gee Gee Gee> 舞曲 …
節目3 : 趙本山表演 <賣柺> 節目 …
結束 : 晚會太棒了, 難忘今宵… 

實現一 : 面向列印程式設計

public class EveningParty {
    public static void main(String[] args) {
        System.out.println("開始 : 晚會開始了…");
        System.out
.println("節目1 : 劉德華演唱 <冰雨> 歌曲 …"); System.out.println("節目2 : 少女時代跳 <Gee Gee Gee> 舞曲 …"); System.out.println("節目3 : 趙本山表演 <賣柺> 節目 …"); System.out.println("結束 : 晚會太棒了, 難忘今宵…"); } }

這裡寫圖片描述

實現二 : 面向物件程式設計

準備資料:

LiuDeHua類

public class LiuDeHua  {

    public
void sing() { System.out.println("節目1 : 劉德華演唱 <冰雨> 歌曲 …"); } }

GirlsGeneration類

public class GirlsGeneration  {

    public void dance() {
        System.out.println("節目2 : 少女時代跳 <Gee Gee Gee> 舞曲 …");
    }
}

ZhaoBenShan類

public class ZhaoBenShan  {

    public void perform
() { System.out.println("節目3 : 趙本山表演 <賣柺> 節目 …"); } }

實現程式碼

public class EveningParty {
    public static void main(String[] args) {

        System.out.println("開始 : 晚會開始了…");

        // 1. 建立一個 `劉德華` 物件
        LiuDeHua liuDeHua = new LiuDeHua();
        liuDeHua.sing();

        // 2. 建立一個 `少女時代` 物件
        GirlsGeneration girls = new GirlsGeneration();
        girls.dance();

        // 3. 建立一個 `趙本山` 物件
        ZhaoBenShan zhaoBenShan = new ZhaoBenShan();
        zhaoBenShan.perform();

        System.out.println("結束 : 晚會太棒了, 難忘今宵…");
    }
}

這裡寫圖片描述

現在,劉德華通告滿了來不了,怎麼辦?請張學友唱歌也可以啊。少女時代解散了不能來跳舞了,怎麼辦?我請少女團伙過來。本山大叔不來演小品了,我請劉謙來變魔術吧。

ZhangXueYou類

public class ZhangXueYou {

    public void sing() {
        System.out.println("節目1 : 張學友演唱 <一路上有你> 歌曲...");
    }
}

GirlsTeam類

public class GirlsTeam {

    public void dance() {
        System.out.println("節目2 : 少女團伙跳 <京東不太熱> 舞曲...");
    }
}

LiuQian類

public class LiuQian  {

    public void perform() {
        System.out.println("節目3 : 劉謙表演 <大變死人> 節目...");
    }
}

程式碼實現

public class EveningParty {
    public static void main(String[] args) {

        System.out.println("開始 : 晚會開始了…");

        // 1. 建立一個 `張學友` 物件
        ZhangXueYou zhangXueYou = new ZhangXueYou();
        zhangXueYou.sing();

        // 2. 建立一個 `少女時代` 物件
        GirlsTeam girls = new GirlsTeam();
        girls.dance();

        // 3. 建立一個 `劉謙` 物件
        LiuQian liuQian = new LiuQian();
        liuQian.perform();

        System.out.println("結束 : 晚會太棒了, 難忘今宵…");
    }
}

實現三 : 面向介面程式設計

我們發現了,需求是舉辦舞會,表演節目是誰我不管,只要晚會舉行了就好。 要唱歌的就來一個唱歌的、要跳舞的就來一個跳舞的、要表演的就來一個會表演的就行。 所以我們可以讓物件實現介面來繼續。

需求 : 舉辦晚會.

開始 : 晚會開始了…
節目1 : 劉德華演唱 <冰雨> 歌曲 …                     找一個唱歌的.
節目2 : 少女時代跳 <Gee Gee Gee> 舞曲 …              找一個跳舞的.
節目3 : 趙本山表演 <賣柺> 節目 …                     找一個表演的.
結束 : 晚會太棒了, 難忘今宵… 

Singable 介面

public interface Singable {
    void sing();
}

Dancable 介面

public interface Dancable {
    void dance();
}

Performable 介面

public interface Performable {
    void perform();
}

讓LiuDeHua、ZhangXueYou實現Singable 介面;

public class LiuDeHua implements Singable {

    @Override
    public void sing() {
        System.out.println("節目1 : 劉德華演唱 <冰雨> 歌曲 …");
    }
}
public class ZhangXueYou implements Singable {

    @Override
    public void sing() {
        System.out.println("節目1 : 張學友演唱 <一路上有你> 歌曲...");
    }
}
GirlsGeneration、GirlsTeam實現 Dancable 介面

public class GirlsGeneration implements Dancable {

@Override
public void dance() {
    System.out.println("節目2 : 少女時代跳 <Gee Gee Gee> 舞曲 …");
}

}

public class GirlsTeam implements Dancable {

    @Override
    public void dance() {
        System.out.println("節目2 : 少女團伙跳 <京東不太熱> 舞曲...");
    }
}

ZhaoBenShan、LiuQian實現 Performable 介面

public class ZhaoBenShan implements Performable {

    @Override
    public void perform() {
        System.out.println("節目3 : 趙本山表演 <賣柺> 節目 …");
    }
}
public class LiuQian implements Performable {

    @Override
    public void perform() {
        System.out.println("節目3 : 劉謙表演 <大變死人> 節目...");
    }
}

實現程式碼:

public class EveningParty {
    public static void main(String[] args) {

        System.out.println("開始 : 晚會開始了…");

        // 1. 建立一個 `張學友` 物件
        Singable s = new ZhangXueYou();
        s.sing();

        // 2. 建立一個 `少女團伙` 物件
        Dancable d = new GirlsTeam();
        d.dance();

        // 3. 建立一個 `劉謙` 物件
        Performable p = new LiuQian();
        p.perform();

        System.out.println("結束 : 晚會太棒了, 難忘今宵…");
    }
}
public class EveningParty {
    public static void main(String[] args) {

        System.out.println("開始 : 晚會開始了…");

        // 1. 建立一個 `劉德華` 物件
        Singable s = new LiuDeHua();
        s.sing();

        // 2. 建立一個 `少女時代` 物件
        Dancable d = new GirlsGeneration();
        d.dance();

        // 3. 建立一個 `趙本山` 物件
        Performable p = new ZhaoBenShan();
        p.perform();

        System.out.println("結束 : 晚會太棒了, 難忘今宵…");
    }
}

實現四 : 工廠設計模式程式設計 換人的流程好像變簡單了。 但是,我的主業務邏輯是舉辦晚會, 到底來誰, 不重要. 那麼為什麼每次換人時, 我的主業務邏輯都需要不停修改呢 ???。 我們應該將晚會需要的 物件 交給一個獨立的類提供. 這個類就被稱為 晚會工廠類. PartyFactory. 作用: 為主業務邏輯提供需要的物件. 這樣就實現了,我的主業務邏輯不變,需要的物件由晚會的工廠類來實現。

// 工廠設計模式 : 配置檔案 + 反射

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class PartyFactory {
    // 屬性
    private static final Properties prop;

    // 靜態程式碼塊
    static {
        prop = new Properties();

        try {
            prop.load(new FileReader("party.properties"));
        } catch (IOException e) {
            throw new RuntimeException("配置檔案載入失敗!");
        }
    }

    public static Singable getSingable() {
        // 1. 根據 key 獲取 prop 物件中的 value
        String className = prop.getProperty("Singable");
        try {
            // 2. 反射建立物件
            Class<?> cls = Class.forName(className);
            Object o = cls.getDeclaredConstructor().newInstance();

            // 3. 強轉, 並返回
            return (Singable) o;
        } catch (Exception e) {
            throw new RuntimeException("物件建立失敗!");
        }
    }

    public static Dancable getDancable() {
        // 1. 根據 key 獲取 prop 物件中的 value
        String className = prop.getProperty("Dancable");
        try {
            // 2. 反射建立物件
            Class<?> cls = Class.forName(className);
            Object o = cls.getDeclaredConstructor().newInstance();

            // 3. 強轉, 並返回
            return (Dancable) o;
        } catch (Exception e) {
            throw new RuntimeException("物件建立失敗!");
        }
    }

    public static Performable getPerformable() {
        // 1. 根據 key 獲取 prop 物件中的 value
        String className = prop.getProperty("Performable");
        try {
            // 2. 反射建立物件
            Class<?> cls = Class.forName(className);
            Object o = cls.getDeclaredConstructor().newInstance();

            // 3. 強轉, 並返回
            return (Performable) o;
        } catch (Exception e) {
            throw new RuntimeException("物件建立失敗!");
        }
    }
}

配置檔案 : party.properties

#Singable=cn.itcast.party.LiuDeHua
#Dancable=cn.itcast.party.GirlsGeneration
#Performable=cn.itcast.party.ZhaoBenShan

Singable=cn.itcast.party.ZhangXueYou
Dancable=cn.itcast.party.GirlsTeam
Performable=cn.itcast.party.LiuQian

實現程式碼:

public class EveningParty {
    public static void main(String[] args) {

        System.out.println("開始 : 晚會開始了…");

        // 1. 晚會工廠類, 給我來一個會唱歌的.
        Singable s = PartyFactory.getSingable();
        s.sing();

        // 2. 晚會工廠類, 給我來一個會跳舞的.
        Dancable d = PartyFactory.getDancable();
        d.dance();

        // 3. 晚會工廠類, 給我來一個會表演的.
        Performable p = PartyFactory.getPerformable();
        p.perform();

        System.out.println("結束 : 晚會太棒了, 難忘今宵…");
    }
}

party.properties就像是晚會表演名單一樣,我只管提需求,而真正幹活的是承辦者也就是晚會工廠類,我不管你給我什麼,我只要晚會能順利舉行就好,這就是設計過程中的 Factorty 設計模式

實現五 : 工廠設計程式設計優化方案

// 工廠設計模式 : 配置檔案 + 反射

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class PartyFactory {
    // 屬性
    private static final Properties prop;

    // 靜態程式碼塊
    static {
        prop = new Properties();

        try {
            prop.load(new FileReader("party.properties"));
        } catch (IOException e) {
            throw new RuntimeException("配置檔案載入失敗!");
        }
    }

    public static <T> T getInstance(Class<T> cls) {
        // 0. 獲取 key
        String key = cls.getSimpleName();

        // 1. 根據 key 獲取 prop 物件中的 value
        String className = prop.getProperty(key);
        try {
            // 2. 反射建立物件
            Class<?> c = Class.forName(className);
            Object o = c.getDeclaredConstructor().newInstance();

            // 3. 強轉, 並返回
            return (T) o;
        } catch (Exception e) {
            throw new RuntimeException("物件建立失敗!");
        }
    }
}

通過反射將程式碼設計的更加簡潔。

配置檔案 : party.properties

#Singable=cn.itcast.party.LiuDeHua
#Dancable=cn.itcast.party.GirlsGeneration
#Performable=cn.itcast.party.ZhaoBenShan

Singable=cn.itcast.party.ZhangXueYou
Dancable=cn.itcast.party.GirlsTeam
Performable=cn.itcast.party.LiuQian

實現程式碼:

public class EveningParty {
    public static void main(String[] args) {

        System.out.println("開始 : 晚會開始了…");

        // 1. 晚會工廠類, 給我來一個會唱歌的.
        Singable s = PartyFactory.getSingable();
        s.sing();

        // 2. 晚會工廠類, 給我來一個會跳舞的.
        Dancable d = PartyFactory.getDancable();
        d.dance();

        // 3. 晚會工廠類, 給我來一個會表演的.
        Performable p = PartyFactory.getPerformable();
        p.perform();

        System.out.println("結束 : 晚會太棒了, 難忘今宵…");
    }
}

執行程式,結果都是下面兩種的一種,但是不管哪一種都實現了我舉辦晚會的需求。

結果1:

這裡寫圖片描述

結果2:

這裡寫圖片描述

工廠設計模式總結

工廠設計模式是一種強調結果而不在乎過程的設計模式。