程式設計設計模式 -- (工廠設計)
一 、工廠設計模式
需求 : 舉辦晚會.
開始 : 晚會開始了…
節目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:
工廠設計模式總結
工廠設計模式是一種強調結果而不在乎過程的設計模式。