在學(xué)習(xí)設(shè)計(jì)模式的時(shí)候,一開始對(duì)其中的工廠方法模式和抽象工廠模式有點(diǎn)混淆美澳,網(wǎng)上查了一下蹲姐,發(fā)現(xiàn)知乎也有人對(duì)這個(gè)問題進(jìn)行提問,看來不止我不懂人柿。一番學(xué)習(xí)好柴墩,發(fā)現(xiàn)其實(shí)很好理解。于是就有這篇文章的輸出
要了解抽象工廠模式凫岖,就要先了解一下簡(jiǎn)單工廠模式和工廠方法模式江咳,這幾種工廠模式,是一步步迭代升級(jí)哥放。至于實(shí)際工作用哪個(gè)更好呢歼指,就要結(jié)合具體需求了。接下來的實(shí)例甥雕,不打算畫UML圖了踩身,畢竟是面向小白,UML可能看不懂社露,也不對(duì)概念進(jìn)行介紹了挟阻,需要的自行網(wǎng)上一搜就一大堆了。就以實(shí)際需求變動(dòng)為例子峭弟,一步步介紹怎樣通過不同的設(shè)計(jì)模式去應(yīng)用附鸽。
作為Android程序員,最熟悉就是手機(jī)了瞒瘸,接下來就通過工廠生產(chǎn)手機(jī)作為例子坷备。
普通寫法
只有一個(gè)產(chǎn)品,正常寫法就是如下情臭,直接創(chuàng)建
# Client.java
/**使用手機(jī)的用戶*/
public class Client {
public static void main(String[] args) {
MiPhone miPhone = new MiPhone();
miPhone.play();
}
}
# MiPhone.java
/**小米手機(jī)對(duì)象類*/
public class MiPhone {
public void play(){
System.out.println("使用小米手機(jī)");
}
}
如果某一天有錢想換成iphone省撑,那應(yīng)該怎樣改了赌蔑?
# Client.java
public class Client {
public static void main(String[] args) {
//MiPhone miPhone = new MiPhone();
//miPhone.play();
Iphone iphone = new Iphone();
iphone.play();
}
}
# IPhone.java
/**新增的iphone手機(jī)對(duì)象類*/
public class Iphone {
public void play(){
System.out.println("使用蘋果手機(jī)");
}
}
在Client
中,我們就才寫了兩行竟秫,都要全部換掉了娃惯,如果還有更多的方法,不都要全部一個(gè)個(gè)改嗎鸿摇?而且石景,這里的產(chǎn)品的創(chuàng)建是在Client
中,正常邏輯我們又不會(huì)自己生產(chǎn)手機(jī)拙吉。這個(gè)時(shí)候潮孽,就可以采用簡(jiǎn)單工廠模式,專業(yè)的東西就讓專業(yè)的工廠去做筷黔。
簡(jiǎn)單工廠模式
# SimpleFactory.java
/**新建一個(gè)工廠內(nèi)往史,通過傳遞不同的參數(shù),創(chuàng)建不同的產(chǎn)品并返回*/
public class SimpleFactory {
public static final String XIAOMI = "xiaomi";
@Nullable
public static ImplPhone createPhone(String phoneName){
if (XIAOMI.equals(phoneName)){
return new MiPhone();
}
return null;
}
}
# ImplPhone.java
/**定義一個(gè)手機(jī)的接口*/
public interface ImplPhone {
void play();
}
/**每個(gè)具體產(chǎn)品都去實(shí)現(xiàn)該接口并實(shí)現(xiàn)方法*/
public class MiPhone implements ImplPhone {
@Override
public void play() {
System.out.println("使用小米手機(jī)");
}
}
public class Client {
public static void main(String[] args) {
// 往工廠類中傳遞不同的值佛舱,就可以得到對(duì)應(yīng)的產(chǎn)品椎例。
ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.XIAOMI);
implPhone.play();
}
}
簡(jiǎn)單工廠模式,就是創(chuàng)建一個(gè)工廠類SimpleFactory
请祖,往工廠類根據(jù)傳遞不同的參數(shù)進(jìn)行條件判斷订歪,生成返回不同的產(chǎn)品類。
這樣改動(dòng)肆捕,就可以避免兩個(gè)問題:
把產(chǎn)品對(duì)象的創(chuàng)建刷晋,統(tǒng)一放在工廠類處理,而不是客戶端自己創(chuàng)建
如果想換手機(jī)慎陵,直接傳遞不同的參數(shù)就好了眼虱。
使用簡(jiǎn)單工廠模式,應(yīng)對(duì)更換手機(jī)的代碼修改
public class SimpleFactory {
public static final String XIAOMI = "xiaomi";
public static final String APPLE = "apple";
public static ImplPhone createPhone(String phoneName){
if (XIAOMI.equals(phoneName)){
return new MiPhone();
}else if (APPLE.equals(phoneName)) {
return new IPhone();
}
return null;
}
}
# Iphone.java
public class IPhone implements ImplPhone {
@Override
public void play() {
System.out.println("使用蘋果手機(jī)");
}
}
public class Client {
public static void main(String[] args) {
// 換成蘋果手機(jī)席纽,就直接傳遞不同參數(shù)生產(chǎn)Iphone手機(jī)了
//ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.XIAOMI);捏悬、
ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.APPLE);、
implPhone.play();润梯、
}
}
工廠方法模式
簡(jiǎn)單工廠模式过牙,基本就可以滿足我們的要求,但是接下來每次新增一個(gè)產(chǎn)品仆救,都要去修改SimpleFactory
類抒和,這個(gè)就不滿足我們的設(shè)計(jì)模式原則,盡量不要影響之前的類彤蔽。于是,工廠方法模式閃亮登場(chǎng)庙洼。
# ImplFactory.java
/**定義一個(gè)工廠類*/
public interface ImplFactory {
ImplPhone cratePhone();
}
# MiFactory.java
/**實(shí)現(xiàn)工廠類顿痪,定義一個(gè)小米工廠镊辕,用于生產(chǎn)小米手機(jī)*/
public class MiFactory implements ImplFactory {
@Override
public ImplPhone cratePhone() {
return new MiPhone();
}
}
# AppleFactory.java
/**實(shí)現(xiàn)工廠類,定義一個(gè)蘋果工廠蚁袭,用于生產(chǎn)iphone手機(jī)*/
public class AppleFactory implements ImplFactory {
@Override
public ImplPhone cratePhone() {
return new IPhone();
}
}
public interface ImplPhone {
void play();
}
public class MiPhone implements ImplPhone {
@Override
public void play() {
System.out.println("使用小米手機(jī)");
}
}
public class IPhone implements ImplPhone {
@Override
public void play() {
System.out.println("使用蘋果手機(jī)");
}
}
public class Client {
public static void main(String[] args) {
ImplFactory factory = new MiFactory();
// 如果想換手機(jī)征懈,只需修改創(chuàng)建的工廠類
// ImplFactory factory = new AppleFactory();
ImplPhone phone = factory.cratePhone();
phone.play();
}
}
用了工廠方法模式,如果新增產(chǎn)品揩悄,比如想換華為呢卖哎,只需要新建一個(gè)華為工廠類去實(shí)現(xiàn)工廠接口,和新建一個(gè)華為手機(jī)內(nèi)去實(shí)現(xiàn)手機(jī)接口删性,就不需要對(duì)原來的代碼進(jìn)行修改了亏娜。但是,人人一部手機(jī)是不夠蹬挺,還要平板了维贺。。巴帮。于是溯泣,ipad,miPad就都出來了榕茧!
抽象工廠模式
上面的ImplFactory
只是cratePhone()
垃沦,根本就沒辦法生產(chǎn)平板,那么用押,就加多條生產(chǎn)線生產(chǎn)肢簿,能賺錢的機(jī)會(huì)怎么可以錯(cuò)過呢?
# ImplFactory.java
/**在原來的抽象工廠中只恨,進(jìn)行修改译仗,增加一條平板的生產(chǎn)線,也就是添加一個(gè)方法*/
public interface ImplFactory {
ImplPhone cratePhone();
ImplPad createPad();
}
public class AppleFactory implements ImplFactory {
@Override
public ImplPhone cratePhone() {
return new IPhone();
}
@Override
public ImplPad createPad() {
return new Ipad();
}
}
public class MiFactory implements ImplFactory {
@Override
public ImplPhone cratePhone() {
return new MiPhone();
}
@Override
public ImplPad createPad() {
return new MiPad();
}
}
public interface ImplPad {
void play();
}
public class Ipad implements ImplPad {
public void play(){
System.out.print("使用ipad");
}
}
public class MiPad implements ImplPad {
public void play(){
System.out.print("使用小米pad");
}
}
public class Client {
public static void main(String[] args) {
ImplFactory factory = new MiFactory();
ImplPhone phone = factory.cratePhone();
phone.play();
ImplPad pad = factory.createPad();
pad.play();
}
}
改動(dòng)還是挺大的官觅,但至少能實(shí)現(xiàn)需求纵菌。接下來有其他廠商也要生產(chǎn)手機(jī)和平板,只需要實(shí)現(xiàn)ImplFactory
就可以了休涤。其實(shí)咱圆,上面的處理方式,就是抽象工廠模式功氨。
靶蛩铡?別驚訝捷凄,一不小心就應(yīng)用上了忱详。仔細(xì)對(duì)比一下區(qū)別就可以理解:
工廠方法模式,重點(diǎn)在方法跺涤,通過實(shí)現(xiàn)同一個(gè)方法匈睁,就可以創(chuàng)建不同的產(chǎn)品监透。
抽象工廠模式,是在工廠方法模式發(fā)展上去的航唆,方法也可以創(chuàng)建不同的產(chǎn)品胀蛮,但是,這個(gè)工廠接口糯钙,變更加抽象了粪狼,在里面可以實(shí)現(xiàn)多個(gè)方法,而不是單一產(chǎn)品了任岸。