本文僅供學(xué)習(xí)交流使用晒衩,侵權(quán)必刪嗤瞎。
不作商業(yè)用途,轉(zhuǎn)載請注明出處浸遗。
WHAT 什么是工廠
工廠模式是一種創(chuàng)建型的設(shè)計(jì)模式猫胁。工廠模式細(xì)分的話會(huì)被分為簡單工廠、工廠方法和抽象工廠這三類跛锌。
我的理解工廠模式就是將子類的實(shí)例化邏輯交給一個(gè)工廠類執(zhí)行弃秆。工廠類利用了面向?qū)ο蠖鄳B(tài)和封裝的特性,將創(chuàng)建對象的邏輯封裝在一個(gè)工廠類中髓帽,然后利用多態(tài)的特性菠赚,根據(jù)條件判斷創(chuàng)建具體的子類的實(shí)例。
簡單工廠
簡單工廠,子類創(chuàng)建邏輯都封裝到一個(gè)工廠類的創(chuàng)建方法中郑藏,簡單明了衡查。但是如果子類對象過多,存在大量邏輯判斷必盖,并將所有的創(chuàng)建邏輯都寫在一個(gè)方法中拌牲,可讀性比較差。此外歌粥,添加子類就需要改動(dòng)原來創(chuàng)建邏輯代碼塌忽,違反開閉原則,而且創(chuàng)建邏輯代碼會(huì)隨著子類的添加而不斷膨脹失驶。
工廠方法
工廠方法,每個(gè)子類的創(chuàng)建都對應(yīng)一個(gè)工廠類土居。如果創(chuàng)建實(shí)例邏輯復(fù)雜,能夠較好將所有創(chuàng)建邏輯分開嬉探,提高可讀性擦耀,工廠類職責(zé)更加單一,并且符合開閉原則涩堤。但如果每添加一個(gè)子類都要添加一個(gè)對應(yīng)的工廠類眷蜓,那么就會(huì)造成類個(gè)數(shù)過多。此外胎围,工廠類的創(chuàng)建會(huì)耦合到調(diào)用函數(shù)中吁系,這個(gè)問題我們可以通過一個(gè)工廠容器解決芹敌,將工廠放到工廠容器我們直接使用即可。
抽象工廠
抽象工廠垮抗,為一類系列的產(chǎn)品創(chuàng)建對象。每個(gè)實(shí)際工廠創(chuàng)建實(shí)際一系列的產(chǎn)品對象碧聪,工廠類是基于產(chǎn)品系列區(qū)分開的冒版。這樣能有效減少工廠類的個(gè)數(shù)。但依然違反了開閉原則逞姿,每次添加一個(gè)產(chǎn)品辞嗡,那么每個(gè)對應(yīng)的實(shí)際工廠都需要做修改。
不過應(yīng)對這種情況我們可以使用反射和配置文件的方式滞造,創(chuàng)建的對象我們可以添加到配置文件续室。創(chuàng)建過程交給框架,既符合開閉原則又符合依賴倒置原則
WHY 為什么使用工廠
- 這種模式能降低了客戶端與產(chǎn)品類的耦合度谒养,客戶端創(chuàng)建一個(gè)產(chǎn)品實(shí)例只需要通過調(diào)用工廠類的創(chuàng)建方法即可挺狰。如果對象實(shí)例化邏輯。
- 將創(chuàng)建邏輯封裝到工廠類中买窟,對調(diào)用者透明丰泊,調(diào)用者無需關(guān)注復(fù)雜的對象創(chuàng)建邏輯,并且能讓原來的方法職責(zé)更單一始绍,代碼更簡潔瞳购,提高了代碼的可讀性。
- 將創(chuàng)建對象代碼邏輯統(tǒng)一封裝在工廠類中亏推,提高了代碼的復(fù)用性
HOW 工廠的實(shí)現(xiàn)(JAVA)
簡單工廠
舉例背景:通過簡單工廠創(chuàng)建不同類型的配置文件解析器
- 解析器類
/**
* 解析器接口類
*/
public interface IConfigParser {
void parse();
}
/**
* 解析器類型
*/
public enum ParserType {
JSON,
XML,
YAML;
}
/**
* json配置文件解析器
*/
public class JsonConfigParser implements IConfigParser {
@Override
public void parse() {
System.out.println("json");
}
}
/**
* xml配置文件解析器
*/
public class XmlConfigParser implements IConfigParser {
@Override
public void parse() {
System.out.println("xml");
}
}
/**
* yaml配置文件解析器
*/
public class YamlConfigParser implements IConfigParser {
@Override
public void parse() {
System.out.println("yaml");
}
}
- 簡單工廠類
public class SimpleFactory {
public static IConfigParser createParser(ParserType type) {
if (type == null) {
return null;
}
if (type == ParserType.JSON) {
return new JsonConfigParser();
} else if (type == ParserType.YAML) {
return new YamlConfigParser();
} else if (type == ParserType.XML) {
return new XmlConfigParser();
} else {
throw new IllegalArgumentException("");
}
}
}
工廠方法
舉例背景:舉例背景:通過工廠方法創(chuàng)建不同類型的配置文件解析器
解析器類同簡單工廠一樣
工廠類
/**
* 工廠類接口
*/
public interface IFactory {
IConfigParser createParser();
}
/**
* Json解析器工廠
*/
public class JsonConfigParserFactory implements IFactory {
@Override
public IConfigParser createParser() {
return new JsonConfigParser();
}
}
/**
* Xml解析器工廠
*/
public class XmlConfigParserFactory implements IFactory {
@Override
public IConfigParser createParser() {
return new XmlConfigParser();
}
}
/**
* Yaml解析器工廠
*/
public class YamlConfigParserFactory implements IFactory {
@Override
public IConfigParser createParser() {
return new YamlConfigParser();
}
}
抽象工廠
舉例背景:根據(jù)不同的數(shù)據(jù)庫類型学赛,創(chuàng)建不同的對象。因?yàn)椴煌臄?shù)據(jù)庫吞杭,有可能對數(shù)據(jù)庫操作也是不一樣的盏浇。我們將對數(shù)據(jù)庫的操作封裝在對應(yīng)的對象中,那么每次根據(jù)數(shù)據(jù)庫類型創(chuàng)建對應(yīng)的對象
- 對象接口類
public interface IUser {
long insert(IUser user);
IUser getUser(String id);
}
public interface IDepartment {
long insert(IDepartment department);
IDepartment getDepartment(String id);
}
- 對象實(shí)現(xiàn)類
public class SqlServerUser implements IUser {
@Override
public long insert(IUser user) {
System.out.println("sqlserver user insert");
return 1;
}
@Override
public IUser getUser(String id) {
return new SqlServerUser();
}
}
public class SqlServerDepartment implements IDepartment {
@Override
public long insert(IDepartment department) {
System.out.println("sqlserver department insert");
return 1L;
}
@Override
public IDepartment getDepartment(String id) {
return new SqlServerDepartment();
}
}
public class MysqlUser implements IUser {
@Override
public long insert(IUser user) {
System.out.println("mysql user insert");
return 1L;
}
@Override
public IUser getUser(String id) {
return new MysqlUser();
}
}
public class MysqlDepartment implements IDepartment {
@Override
public long insert(IDepartment department) {
System.out.println("mysql department insert");
return 1L;
}
@Override
public IDepartment getDepartment(String id) {
return new MysqlDepartment();
}
}
- 工廠類
/**
* 抽象工廠類
*/
public abstract class AbstractFactory {
public abstract IUser createUser();
public abstract IDepartment createDepartment();
}
/**
* Mysql工廠類
*/
public class MysqlFactory extends AbstractFactory {
@Override
public IUser createUser() {
return new MysqlUser();
}
@Override
public IDepartment createDepartment() {
return new MysqlDepartment();
}
}
/**
* SqlServer工廠類
*/
public class SqlServerFactory extends AbstractFactory {
@Override
public IUser createUser() {
return new SqlServerUser();
}
@Override
public IDepartment createDepartment() {
return new SqlServerDepartment();
}
}