第1章 工廠模式概述
1-1 工廠模式概述
什麼是設計模式?
設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、
代碼設計經驗總結。
應用設計模式有什麼好處?
設計模式是優秀的使用案例,使用設計模式可提高代碼的重用性、讓代碼更容易被他人理解、
保證代碼可靠性。
- 工廠模式的概念
- 工廠模式的意圖
- 工廠模式的應用場景
- 工廠模式的設計思想
- 工廠模式的好處
工廠模式概率:
實例化對象,用工廠方法代替new操作。
工程模式包括工廠方法模式和抽象工廠模式。
抽象工廠模式是工廠方法模式的擴展。
工廠模式的意圖:
定義一個接口來創建對象,但是讓子類來決定哪些類需要被實例化。
工廠方法把實例化的工作推遲到子類中去實現。
什麼情況下適合工廠模式?
- 有一組類似的對象需要創建。
- 在編碼時不能預見需要創建哪些種類的實例。
- 系統需要考慮擴展性,不應依賴於產品類實例如何被創建、組合和表達的細節。
項目中的狀況:
在軟件系統中經常面臨着“對象”的創建工作,由於需求的變化,這個對象可能隨之
發生改變,但它卻擁有比較穩定的接口。
爲此,我們需要提供一種封裝機制來隔離出這個易變對象的變化,從而保持系統中
其他依賴該對象的對象不隨這需求變化而變化。
基於項目狀態將代碼進行如下設計:
- 儘量鬆耦合,一個對象的依賴對象的變化與本身無關
- 具體產品與客戶端剝離,責任分割
客戶端–>creator–>Interface<–product1、2、3
多個產品族,就是抽象工廠模式
應用場景舉例
myotee臉萌,一款製作頭像的軟件
可以自由選擇髮型,髮色,臉型,膚色,眉毛,眼鏡,嘴巴,鼻子等。
以髮型爲例,髮型是這個大產品中的一個小部件,如果製作出了髮型,其它部分也都
相似。再有更高級的應用,不同的用戶級別需要不同的產品部件,這樣就產生了一個
產品系列。
第2章 工廠模式應用
2-1 工廠模式應用
/**
* 髮型接口
* @author Administrator
*
*/
public interface HairInterface {
/**
* 畫圖
*/
public void draw();
}
/**
* 左偏分發型
* @author Administrator
*
*/
public class LeftHair implements HairInterface {
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println("-----------------左偏分發型-------------------");
}
}
/**
* 右偏分發型
* @author Administrator
*
*/
public class RightHair implements HairInterface {
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println("-----------------右偏分發型-------------------");
}
}
/**
* properties文件的讀取工具
* @author Administrator
*
*/
public class PropertiesReader {
public Map<String, String> getProperties() {
Properties props = new Properties();
Map<String, String> map = new HashMap<String, String>();
try {
InputStream in = getClass().getResourceAsStream("type.properties");
props.load(in);
Enumeration en = props.propertyNames();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String property = props.getProperty(key);
map.put(key, property);
// System.out.println(key + " " + property);
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
}
left=com.sunny.project.LeftHair
right=com.sunny.project.RightHair
in=com.sunny.project.InHair
/**
* 中分發型
* @author Administrator
*
*/
public class InHair implements HairInterface {
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println("-----------------中分發型-------------------");
}
}
/**
* 髮型工廠
* @author Administrator
*
*/
public class HairFactory {
/**
* 根據類型來創建對象
* @param key
* @return
*/
public HairInterface getHair(String key){
if("left".equals(key)){
return new LeftHair();
}else if("right".equals(key)){
return new RightHair();
}
return null;
}
/**
* 根據類的名稱來生產對象
* @param className
* @return
*/
public HairInterface getHairByClass(String className){
try {
HairInterface hair = (HairInterface) Class.forName(className).newInstance();
return hair;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 根據類的名稱來生產對象
* @param className
* @return
*/
public HairInterface getHairByClassKey(String key){
try {
Map<String, String> map = new PropertiesReader().getProperties();
HairInterface hair = (HairInterface) Class.forName(map.get(key)).newInstance();
return hair;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
第3章 抽象工廠模式應用
3-1 抽象工廠模式應用
/**
* 男孩
* @author Administrator
*
*/
public interface Boy {
public void drawMan();
}
/**
* 女孩子
* @author Administrator
*
*/
public interface Girl {
public void drawWomen();
}
/**
* 聖誕系列的女孩
* @author Administrator
*
*/
public class MCGirl implements Girl {
@Override
public void drawWomen() {
// TODO Auto-generated method stub
System.out.println("-----------------聖誕系列的女孩子--------------------");
}
}
/**
* 新年系列的女孩子
* @author Administrator
*
*/
public class HNGirl implements Girl {
@Override
public void drawWomen() {
// TODO Auto-generated method stub
System.out.println("-----------------新年系列的女孩子--------------------");
}
}
/**
* 聖誕系列的男孩子
* @author Administrator
*
*/
public class MCBoy implements Boy {
@Override
public void drawMan() {
// TODO Auto-generated method stub
System.out.println("-----------------聖誕系列的男孩子--------------------");
}
}
/**
* 新年系列的男孩子
* @author Administrator
*
*/
public class HNBoy implements Boy {
@Override
public void drawMan() {
// TODO Auto-generated method stub
System.out.println("-----------------新年系列的男孩子--------------------");
}
}
/**
* 人物的實現接口
* @author Administrator
*
*/
public interface PersonFactory {
//男孩接口
public Boy getBoy();
//女孩接口
public Girl getGirl();
}
/**
* 聖誕系列加工廠
* @author Administrator
*
*/
public class MCFctory implements PersonFactory {
@Override
public Boy getBoy() {
// TODO Auto-generated method stub
return new MCBoy();
}
@Override
public Girl getGirl() {
// TODO Auto-generated method stub
return new MCGirl();
}
}
/**
* 新年系列加工廠
* @author Administrator
*
*/
public class HNFactory implements PersonFactory {
@Override
public Boy getBoy() {
// TODO Auto-generated method stub
return new HNBoy();
}
@Override
public Girl getGirl() {
// TODO Auto-generated method stub
return new HNGirl();
}
}
public class SunnyTest {
public static void main(String[] args){
// HairInterface left = new LeftHair();
// left.draw();
HairFactory factory = new HairFactory();
// HairInterface right = factory.getHair("right");
// right.draw();
// HairInterface left = factory.getHairByClass("com.sunny.project.LeftHair");
// left.draw();
// HairInterface hair = factory.getHairByClassKey("in");
// hair.draw();
// PersonFactory facoty = new MCFctory();
// Girl girl = facoty.getGirl();
// girl.drawWomen();
PersonFactory facoty = new HNFactory();
Boy boy = facoty.getBoy();
boy.drawMan();
}
}
第4章 總結
4-1 總結
常見應用
- JDBC
是一種用於執行SQL語句的Java API,可以爲多種關係數據庫提供統一訪問,它由一組用
Java語言編寫的類和接口組成。
客戶端–>數據操作工程–>jdbc接口<–db2/mysql/oracle/sqlserver - Spring BeanFactroy
BeanFactroy,作爲Spring基礎的IoC容器,是Spring的一個Bean工廠。
如果單從工廠模式的角度來考慮,它就是用來“生產 Bean”,然後提供給
客戶端。
Bean的實例化過程如下:
- 調用Bean的默認構造方法,或指定的構造方法,生成bean實例(暫稱爲instance1)
- 如果Bean的配置文件中注入了Bean的屬性值,則在instance基礎上進行屬性注入形成
instance2,這種注入是覆蓋性的 - 如果Bean實現了InitializingBean接口,則調用afterPropertiesSet()方法,來改變或
操作instance2,得到instance3 - 如果Bean的配置文件中指定了init-method=”init”屬性,則會調用指定的初始化方法
則在instance3的基礎上調用初始化方法init(),將對象最終初始化爲instance4;當然
這個初始化的名字是任意的
工廠方法模式和抽象工廠模式對比
- 工廠模式是一種極端情況的抽象工廠模式,而抽象模式可以看成是工廠模式的推廣
- 工廠模式用來創建一個產品等級結構,而抽象工廠模式是用來創建多個產品的等級結構
- 工廠模式只有一個抽象產品類,而抽象工廠模式有多個抽象產品類
工廠模式的實現幫助我們
- 系統可以在不修改具體工廠角色的情況下引進新的產品
- 客戶端不必關心對象如何創建,明確了職責
- 更好的理解面向對象的原則 面向接口編程,而不要面向實現編程
工廠模式適用於哪些場景
- 一個系統應當不依賴於產品類實例被創立,組成,和表示的細節。這對於所有
形態的工廠模式都是重要的 - 這個系統的產品有至少一個的產品族
- 同屬於同一個產品族的產品是設計成在一起使用的。這一約束必須得在系統的設計
中體現出來 - 不同的產品以一系列的接口的面貌出現,從而使系統不依賴於接口實現的細節