工廠模式
什麼是設計模式?
設計模式就是經過前人無數次的實踐總結出的,設計過程中可以反覆使用的、可以解決特定問題的設計方法,也就是一套被反覆使用,多數人知曉的,經過分類編目的,代碼設計經驗的總結
其目的是:使用設計模式是爲了可重用代碼,讓代碼更容易被他人理解,保證代碼的可靠性。
工廠模式的概念
實列化對象,用工廠方法代替new操作
工廠模式包括工廠方法模式和抽象工廠模式
抽象工廠模式是工廠方法模式的擴展
工廠模式的意圖
定義一個接口來創建對象,但是讓子類決定哪些類需要被實例化
工廠方法把實例化的工作推遲到子類中去實現
工廠模式的應用場景
有一組類似的對象需要創建
在編碼時不能預見需要創建那種類的實例
系統需要考慮擴展性,不應依賴於產品類實例如何被創建,組合和表達細節
工廠模式的動機
項目中的現狀:
在軟件系統中經常面臨着“對象”的創建工作,由於需求的變化,這個對象可能隨之也會發生變化,但它擁有着比較穩定的接口
爲此,我們需要提供一種封裝機制來隔離出這個易變對象的變化,從而保持系統中其他依賴該對象的對象不隨着需求變化而變化
基於項目現狀將代碼進行如下設計:
1.儘量鬆耦合,一個對象的依賴對象的變化與本身無關
2.具體產品與客戶端剝離,責任分割
髮型工廠實例demo
實現接口
package com.example.demo.test3;
/**
* 髮型接口
*/
public interface HairInterface {
//實現髮型
public void draw();
}
左偏分發型
package com.example.demo.test3;
/**
* 左偏分發型
*/
public class LeftHair implements HairInterface{
/**
* 畫一個左偏分發型
*/
@Override
public void draw() {
System.out.println("實現左偏分發型");
}
}
右偏分發型
package com.example.demo.test3;
public class RightHair implements HairInterface {
@Override
public void draw() {
System.out.println("實現一個右偏分的髮型");
}
}
髮型工廠
package com.example.demo.test3;
import java.util.HashMap;
import java.util.Map;
/**
* 髮型工廠
*/
public class HairFactory {
/**
* 更加類型 來創建對象
* @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 (Exception e){
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 (Exception e){
e.printStackTrace();;
}
return null;
}
}
Properties讀取類
package com.example.demo.test3;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Properties讀取類
*/
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);
}
}catch (Exception e){
e.printStackTrace();
}
return map;
}
}
type.properties
left=com.example.demo.test3.LeftHair
right=com.example.demo.test3.RightHair
測試方法
package com.example.demo.test3;
/**
* 模擬客戶端實現
*/
public class Test {
public static void main(String[] args) {
//實現左偏分
// HairInterface left=new LeftHair();
// left.draw();
HairFactory factory=new HairFactory();
// HairInterface left=factory.getHair("left");
// left.draw();
// HairInterface left= factory.getHairByClass("com.example.demo.test3.LeftHair");
//left.draw();
HairInterface left=factory.getHairByClassKey("left");
left.draw();
}
}
節日皮膚接口demo
男孩接口
package com.example.demo.test3;
/**
* 男孩
*/
public interface Boy {
public void drawMan();
}
女孩接口
package com.example.demo.test3;
/**
* 女孩
*/
public interface Girl {
public void DrawWomen();
}
男孩新年系列皮膚
package com.example.demo.test3;
/**
* 新年系列男孩子
*/
public class HNBoy implements Boy{
@Override
public void drawMan() {
System.out.println("新年系列男孩子");
}
}
男孩聖誕系列皮膚
package com.example.demo.test3;
/**
* 聖誕系列的男孩子
*/
public class MCBoy implements Boy{
@Override
public void drawMan() {
System.out.println("聖誕系列的男孩子");
}
}
女孩子新年系列皮膚
package com.example.demo.test3;
public class HNGirl implements Girl{
@Override
public void DrawWomen() {
System.out.println("新年系列的女孩子");
}
}
女孩子聖誕系列皮膚
package com.example.demo.test3;
/**
* 聖誕系列的女孩
*/
public class MCGirl implements Girl{
@Override
public void DrawWomen() {
System.out.println("聖誕系列的女孩子");
}
}
男孩女孩接口
package com.example.demo.test3;
public interface PersonFactory {
//男孩接口
public Boy getBoy();
//女孩接口
public Girl getGirl();
}
新年系列工廠
package com.example.demo.test3;
/**
* 新年系列加工廠
*/
public class HNFctory implements PersonFactory{
@Override
public Boy getBoy() {
return new HNBoy();
}
@Override
public Girl getGirl() {
return new HNGirl();
}
}
聖誕系列工廠
package com.example.demo.test3;
/**
* 聖誕系列加工廠
*/
public class MCFctory implements PersonFactory {
@Override
public Boy getBoy() {
return new MCBoy();
}
@Override
public Girl getGirl() {
return new MCGirl();
}
}
測試類
package com.example.demo.test3;
/**
* 模擬客戶端實現
*/
public class Test {
public static void main(String[] args) {
//實現左偏分
// HairInterface left=new LeftHair();
// left.draw();
// HairFactory factory=new HairFactory();
// HairInterface left=factory.getHair("left");
// left.draw();
// HairInterface left= factory.getHairByClass("com.example.demo.test3.LeftHair");
//left.draw();
// HairInterface left=factory.getHairByClassKey("left");
// left.draw();
PersonFactory facoty=new MCFctory();
Girl girl=facoty.getGirl();
girl.DrawWomen();
PersonFactory personFactory=new HNFctory();
Boy boy=personFactory.getBoy();
boy.drawMan();
}
}
總結
工廠方法模式和抽象工廠模式對比
1.工廠模式時一種極端情況的抽象工廠模式,而抽象工廠模式可以看成時工廠模式的推廣
2.工廠模式用來創建一個產品的等級結構,而抽象工廠模式是用來創建多個產品的等級結構
3.工廠模式只有一個抽象產品類,而抽象工廠模式有多個抽象產品類
工廠模式的實現幫助我們
1.系統可以在不修改具體工廠角色的情況下引進新的產品
2.客戶端不必關心對象如果創建,明確了職責
3.更好的理解面向對象的原則 面向接口編程,而不要面向實現編程
工廠模式適用與哪些場景呢?
1.一個系統應當不依賴於產品類實例被創立,組成,和表示的細節。這對於所有形態的工廠模式都是重要的
2.這個系統的產品有至少一個的產品族
3.同屬於同一個產品族的產品是設計成在一起使用的。這一約束必須得在系統的設計中體現出來
4.不同的產品以一系列的接口面貌出現,從而使系統不依賴於接口實現的細節
工廠模式常用於
如:JDBC ,SpringBean