Android 架構(gòu)師之路6 設(shè)計模式之工廠模式

Android 架構(gòu)師之路 目錄

前言

工廠模式中恨溜,重要的是工廠類符衔,而不是產(chǎn)品類。產(chǎn)品類可以是多種形式糟袁,多層繼承或者是單個類都是可以的判族。但要明確的,工廠模式的接口只會返回一種類型的實例系吭,這是在設(shè)計產(chǎn)品類的時候需要注意的五嫂,最好是有父類或者共同實現(xiàn)的接口。
使用工廠模式肯尺,返回的實例一定是工廠創(chuàng)建的沃缘,而不是從其他對象中獲取的。
工廠模式返回的實例可以不是新創(chuàng)建的则吟,返回由工廠創(chuàng)建好的實例也是可以的槐臀。

工廠模式主要是為創(chuàng)建對象提供了接口。工廠模式按照《Java與模式》中的提法分為三類:

  1. 簡單工廠模式(Simple Factory)
  2. 工廠方法模式(Factory Method)
  3. 抽象工廠模式(Abstract Factory)

1氓仲、工廠模式 - 簡單工廠模式

簡單工廠優(yōu)點:客戶端可以免除直接創(chuàng)建產(chǎn)品對象的責(zé)任水慨,而僅僅是“消費”產(chǎn)品。簡單工廠模式通過這種做法實現(xiàn)了對責(zé)任的分割敬扛。

1.1晰洒、 簡單工廠模式UML圖
簡單工廠模式UML圖
1.2、 代碼實現(xiàn)
定義接口
/**
 * 地圖規(guī)范
 * @author Dream
 *
 */
public interface IMapView {
    enum MapType {
        // 空白背景模式常量
        MAP_TYPE_NONE,
        // 普通地圖模式常量
        MAP_TYPE_NORMAL,
        // 衛(wèi)星圖模式常量
        MAP_TYPE_SATELLITE
    }

    public View getView();

    public void setMapType(MapType mapType);
}
實現(xiàn)接口
public class BaiduMapView implements IMapView {

    @Override
    public View getView() {
        System.out.println("調(diào)用了百度地圖的getView");
        return null;
    }

    @Override
    public void setMapType(MapType mapType) {
        System.out.println("調(diào)用了百度地圖的setMapType");
    }

}

public class GaodeMapView implements IMapView {

    @Override
    public View getView() {
        System.out.println("調(diào)用了高德地圖的getView");
        return null;
    }

    @Override
    public void setMapType(MapType mapType) {
        System.out.println("調(diào)用了高德地圖的setMapType");
    }

}

創(chuàng)建工廠類
public class MapViewFactory {
    
    enum MapType{
        Baidu,
        Gaode
    }
    
    //使用上一節(jié)課的內(nèi)容---單例模式
    //懶漢式
    private static MapViewFactory mapViewFactory;
    
    private MapViewFactory(){
        
    }
    
    public static MapViewFactory getInstance(){
        if(mapViewFactory == null){
            mapViewFactory = new MapViewFactory();
            ArrayList<String> list = new ArrayList<String>();
            HashSet<String> hashSet = new HashSet<String>();
        }
        return mapViewFactory;
    }
    
    public IMapView getMapView(MapType mapType){
        IMapView mapView = null;
        switch (mapType) {
        case Baidu:
            mapView = new BaiduMapView();
            break;
        case Gaode:
            mapView = new GaodeMapView();
            break;
        }
        return mapView;
    }
    
}
調(diào)用主函數(shù)
public class SimpleTest {

    public static void main(String[] args) {
        // 客戶端和我們的地圖模塊耦合度大大降低了
        IMapView mapView = MapViewFactory.getInstance().getMapView(
                MapViewFactory.MapType.Baidu);
        mapView.getView();
        mapView.setMapType(IMapView.MapType.MAP_TYPE_NONE);
    }

}

運行結(jié)果
獲得百度地圖MapView
設(shè)置了高德地圖類型
獲得高德地圖MapView
設(shè)置了高德地圖類型
1.3啥箭、Android源碼中使用
Android中簡單工廠--BitmapFactory,XmlPullParserFactory,CertificateFactory

2谍珊、工廠模式 - 工廠方法模式

工廠方法模式:把對象的實現(xiàn)延遲到子類完成
工廠方法優(yōu)點:允許系統(tǒng)在不修改具體工廠角色的情況下引進新產(chǎn)品。

2.1急侥、 工廠方法模式UML圖
工廠方法模式UML圖
2.2砌滞、 代碼實現(xiàn)
產(chǎn)品接口與實現(xiàn)(Mapview)
//接口
public abstract class IMapView {
    public abstract void onStart();

    public abstract void onResume();

    public abstract void onDestory();
}
public class BaiduMapView extends IMapView {

    @Override
    public void onStart() {
        System.out.println("百度地圖onStart");
    }

    @Override
    public void onResume() {
        System.out.println("百度地圖onResume");
    }

    @Override
    public void onDestory() {
        System.out.println("百度地圖onDestory");
    }

}
public class GaodeMapView extends IMapView {

    @Override
    public void onStart() {
        System.out.println("高德地圖onStart");
    }

    @Override
    public void onResume() {
        System.out.println("高德地圖onResume");

    }

    @Override
    public void onDestory() {
        System.out.println("高德地圖onResume");
    }

}
抽象工廠
//抽象
public abstract class AbsMapFactory {
    // 我只定義標準
    public abstract <T extends IMapView> T createMapView(Class<T> clzz);
}

實現(xiàn)工廠
public class DefaultMapFactory extends AbsMapFactory {

    private static DefaultMapFactory defaultMapFactory;

    private DefaultMapFactory() {
    }

    public static DefaultMapFactory getInstance(){
        if(defaultMapFactory == null){
            defaultMapFactory = new DefaultMapFactory();
        }
        return defaultMapFactory;
    }


    @Override
    public <T extends IMapView> T createMapView(Class<T> clzz) {
        try {
            // 反射
            return clzz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
調(diào)用主函數(shù)
public class TestClient {
    
    public static void main(String[] args) {
        //工廠方法模式
        AbsMapFactory factory = DefaultMapFactory.getInstance();
        BaiduMapView mapView = factory.createMapView(BaiduMapView.class);
        mapView.onStart();

    }
    
}

運行結(jié)果
百度地圖onStart
2.2、 Java或Android中源碼運用

分析List集合坏怪、Set集合贝润、Map集合 源碼
lterator:遍歷集合工廠方法抽象
Itr:具體的工廠實現(xiàn)類

lterator-> 抽象(工廠方法抽象) -->AdsMapFactory
Itr ->具體實現(xiàn)類->DefaultMapFactory
AbstractList-> 抽象 -->ImapView

      ArrayList-> 實現(xiàn)類-->  BaiduMapView

3、工廠模式 - 抽象工廠模式

為了增加導(dǎo)航模塊铝宵、全景圖口快打掘、定位模塊而不僅僅是地圖模塊引入抽象工廠模式 (一組類要求相同約束)
抽象工廠優(yōu)點:向客戶端提供一個接口,使得客戶端在不必指定產(chǎn)品具體類型的情況下,創(chuàng)建多個產(chǎn)品族中的產(chǎn)品對象

3.1胧卤、 抽象工廠模式UML圖
抽象工廠模式UML圖
3.2唯绍、 代碼實現(xiàn)
抽象工廠
public abstract class AbsMapFactory {

    public abstract AbsMapView createMapView();

    public abstract AbsMapNavigation createMapNavigation();

    public abstract AbsMapLocation createMapLocation();
}

各種具體工廠
public class GaodeMapFactory extends AbsMapFactory {

    @Override
    public AbsMapView createMapView() {
        return new GaodeMapView();
    }

    @Override
    public AbsMapNavigation createMapNavigation() {
        return new GaodeMapNavigation();
    }

    @Override
    public AbsMapLocation createMapLocation() {
        return new GaodeMapLocation();
    }

}
public class BaiduMapFactory extends AbsMapFactory {

    @Override
    public AbsMapView createMapView() {

        return  new BaiduMapView();
    }

    @Override
    public AbsMapNavigation createMapNavigation() {

        return new BaiduMapNavigation();
    }

    @Override
    public AbsMapLocation createMapLocation() {
        return new BaiduMapLocation();
    }

}
初始化工廠
public class DefaultFactory {


    //使用反射
    public static  <T extends AbsMapFactory> T creatProduct(Class<T> clz){
        AbsMapFactory api =null;
        try {
            api =(AbsMapFactory) Class.forName(clz.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return (T)api;
    }

}

工廠內(nèi)各產(chǎn)品

定位產(chǎn)品

public abstract class AbsMapLocation {
    
    /**
     * 定位
     */
    public abstract void location();
}

public class BaiduMapLocation extends AbsMapLocation {

    @Override
    public void location() {
        System.out.println("百度地圖定位...");
    }

}
public class GaodeMapLocation extends AbsMapLocation {

    @Override
    public void location() {
        System.out.println("高德地圖定位...");
    }

}

地圖產(chǎn)品

public abstract class AbsMapView {
    
    /**
     * Result for IActivityManager.startActivity: an error where the
     * start had to be canceled.
     * @hide
     */
    public abstract void onStart();

    public abstract void onResume();

    public abstract void onDestory();
}

public class BaiduMapView extends AbsMapView {

    
    @Override
    public void onStart() {
        System.out.println("百度地圖調(diào)用了onStart");
    }

    @Override
    public void onResume() {
        System.out.println("百度地圖調(diào)用了onResume");
    }

    @Override
    public void onDestory() {
        System.out.println("百度地圖調(diào)用了onDestory");
    }

}
public class GaodeMapView extends AbsMapView {

    @Override
    public void onStart() {
        System.out.println("高德地圖調(diào)用了onStart");
    }

    @Override
    public void onResume() {
        System.out.println("高德地圖調(diào)用了onResume");
    }

    @Override
    public void onDestory() {
        System.out.println("高德地圖調(diào)用了onDestory");
    }

}

導(dǎo)航產(chǎn)品

public abstract class AbsMapNavigation {
    
    /**
     * 路線規(guī)劃
     */
    public abstract void turnByTurn();
    
    //......很多功能方法
}
public class BaiduMapNavigation extends AbsMapNavigation {

    @Override
    public void turnByTurn() {
        System.out.println("百度地圖導(dǎo)航路線規(guī)劃");
    }

}
public class GaodeMapNavigation extends AbsMapNavigation {

    @Override
    public void turnByTurn() {
        System.out.println("高德地圖導(dǎo)航功能路線規(guī)劃");
    }

}

調(diào)用主函數(shù)


public class Test {
    
    public static void main(String[] args) {
        //直接初始化某地圖
        AbsMapFactory factory = new BaiduMapFactory();
        factory.createMapView().onStart();
        factory.createMapLocation().location();

        //反射初始化某地圖
        AbsMapFactory factory2 =  DefaultFactory.creatProduct(GaodeMapFactory.class);
        factory2.createMapView().onStart();
        factory2.createMapLocation().location();
    }
}
運行結(jié)果
百度地圖調(diào)用了onStart
百度地圖定位...
高德地圖調(diào)用了onStart
高德地圖定位...
3.3、 Android源碼中使用

Activity、Service --- AbsMapView或者AbsMapNavgation
我們自定義的Activity(如BaseActivity)、Service ---BaiduMapView 或 BaiduMapNavgation
ActivityManager么伯、ServiceManager --- 類似于我們通常所說的AbsMapFactory

總結(jié):

簡單工廠 : 用來生產(chǎn)同一等級結(jié)構(gòu)中的任意產(chǎn)品忍饰。(對于增加新的產(chǎn)品,無能為力)
工廠方法 :用來生產(chǎn)同一等級結(jié)構(gòu)中的固定產(chǎn)品耐版。(支持增加任意產(chǎn)品)
抽象工廠 :用來生產(chǎn)不同產(chǎn)品族的全部產(chǎn)品祠够。(對于增加新的產(chǎn)品,無能為力粪牲;支持增加產(chǎn)品族)

以上三種工廠 方法在等級結(jié)構(gòu)和產(chǎn)品族這兩個方向上的支持程度不同古瓤。所以要根據(jù)情況考慮應(yīng)該使用哪種方法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腺阳,一起剝皮案震驚了整個濱河市落君,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亭引,老刑警劉巖绎速,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異焙蚓,居然都是意外死亡纹冤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門购公,熙熙樓的掌柜王于貴愁眉苦臉地迎上來萌京,“玉大人,你說我怎么就攤上這事宏浩≈校” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵绘闷,是天一觀的道長橡庞。 經(jīng)常有香客問我,道長印蔗,這世上最難降的妖魔是什么扒最? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任华嘹,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘岔霸。我一直安慰自己,他們只是感情好俯渤,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布呆细。 她就那樣靜靜地躺著八匠,像睡著了一般絮爷。 火紅的嫁衣襯著肌膚如雪梨树。 梳的紋絲不亂的頭發(fā)上坑夯,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音抡四,去河邊找鬼柜蜈。 笑死指巡,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的厌处。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缆娃,長吁一口氣:“原來是場噩夢啊……” “哼瑰排!你這毒婦竟也來了贯要?” 一聲冷哼從身側(cè)響起椭住,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤京郑,失蹤者是張志新(化名)和其女友劉穎宅广,沒想到半個月后些举,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡驶臊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扛门。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纵寝。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖店雅,靈堂內(nèi)的尸體忽然破棺而出政基,到底是詐尸還是另有隱情闹啦,我是刑警寧澤辕坝,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站琳袄,受9級特大地震影響纺酸,放射性物質(zhì)發(fā)生泄漏窖逗。R本人自食惡果不足惜餐蔬,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仗考。 院中可真熱鬧,春花似錦秃嗜、人聲如沸顿膨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至顾画,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間研侣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工惦银, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扯俱。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓喇澡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親晴玖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 設(shè)計模式匯總 一让簿、基礎(chǔ)知識 1. 設(shè)計模式概述 定義:設(shè)計模式(Design Pattern)是一套被反復(fù)使用秀睛、多...
    MinoyJet閱讀 3,947評論 1 15
  • 今天學(xué)習(xí)下最常見的工廠模式,工廠模式細分下來有三大類: 他們的目標都是一樣的:封裝對象的創(chuàng)建椭迎。但是實現(xiàn)手段和使用場...
    西木柚子閱讀 2,153評論 7 28
  • 1.接口基礎(chǔ)回顧 設(shè)計模式六大原則藤抡,其中依賴倒轉(zhuǎn)原則侠碧,強調(diào)我們應(yīng)該面向接口編程缠黍,那什么是接口?接口的作用? 接口如...
    孟婆湯不解渴閱讀 847評論 0 3
  • 最近看了一本書,《我在海軍航母上的8年》视卢。書中記述了一個中國人在美國當海軍的故事廊驼。讀這本書据过,是因為好奇。我的同事最...
    wifim閱讀 1,927評論 4 0
  • 夜深了西饵。 陰沉沉的天空終于下起了大雨鳞芙。 漆黑的夜幕被一道光劈成了兩半眷柔,整個城市被照的亮堂堂的原朝,緊隨而至的是一...
    莫甘棠閱讀 257評論 0 0