ANDROID 中设计模式的採用–创建型模式[通俗易懂]

ANDROID 中设计模式的採用–创建型模式

大家好,又见面了,我是全栈君。



        所谓模式就是在某一情景下解决某个问题的固定解决方式。

        全部的创建型模式都是用作对象的创建或实例化的解决方式。

        1 简单工厂模式

创建对象的最简单方法是使用new来创建一个对象,假设仅仅创建一种固定不变的对象,能够使用new来创建这个对象。

假设要依据不同场景创建不同类型的对象,就可能须要採用不同的方法,就出现了不同的模式的採用和总结。

ANDROID的媒体框架中为了实现对不同媒体源的播放,就须要实现多种播放器对象,并可能须要依据支持的媒体类型的添加,不断加入播放器对象。

 sp<MediaPlayerBase> p;
    switch (playerType) {
        case SONIVOX_PLAYER:
            ALOGV(" create MidiFile");
            p = new MidiFile();
            break;
        case STAGEFRIGHT_PLAYER:
            ALOGV(" create StagefrightPlayer");
            p = new StagefrightPlayer;
            break;
        case NU_PLAYER:
            ALOGV(" create NuPlayer");
            p = new NuPlayerDriver;
            break;
        case TEST_PLAYER:
            ALOGV("Create Test Player stub");
            p = new TestPlayerStub();
            break;
       case   AAH_RX_PLAYER:
            ALOGV(" create A@H RX Player");
            p = createAAH_RXPlayer();
            break;
        case  AAH_TX_PLAYER:
            ALOGV(" create A@H TX Player");
            p = createAAH_TXPlayer();
            break;
#ifdef BUILD_WITH_MST
        case MST_PLAYER:
            ALOGV(" create MstPlayer");
            p = new MstPlayer;
            break;
#endif
        default:
            ALOGE("Unknown player type: %d", playerType);
            return NULL;
    }

上面代码可能随着播放支持的媒体类型的加入须要不断改动。因此为了满足“开闭设计原则”(对改动封闭,对扩展开放)。就要採用不同的模式实现媒体播放器对象的创建功能。

一种简单的方法是把上面的代码放到一个创建播放器的函数中。这也是ANDROID4.2曾经的版本号採用的模式,也称为简单工厂之静态工厂模式。

就如以下所看到的:

static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
        notify_callback_f notifyFunc)
{
  sp<MediaPlayerBase> p;
    switch (playerType) {
        case SONIVOX_PLAYER:
            ALOGV(" create MidiFile");
            p = new MidiFile();
            break;
        case STAGEFRIGHT_PLAYER:
            ALOGV(" create StagefrightPlayer");
            p = new StagefrightPlayer;
            break;
        case NU_PLAYER:
            ALOGV(" create NuPlayer");
            p = new NuPlayerDriver;
            break;
        case TEST_PLAYER:
            ALOGV("Create Test Player stub");
            p = new TestPlayerStub();
            break;
       case   AAH_RX_PLAYER:
            ALOGV(" create A@H RX Player");
            p = createAAH_RXPlayer();
            break;
        case  AAH_TX_PLAYER:
            ALOGV(" create A@H TX Player");
            p = createAAH_TXPlayer();
            break;
#ifdef BUILD_WITH_MST
        case MST_PLAYER:
            ALOGV(" create MstPlayer");
            p = new MstPlayer;
            break;
#endif
        default:
            ALOGE("Unknown player type: %d", playerType);
            return NULL;
    }
  sp<MediaPlayerBase> p;
    switch (playerType) {
        case SONIVOX_PLAYER:
            ALOGV(" create MidiFile");
            p = new MidiFile();
            break;
        case STAGEFRIGHT_PLAYER:
            ALOGV(" create StagefrightPlayer");
            p = new StagefrightPlayer;
            break;
        case NU_PLAYER:
            ALOGV(" create NuPlayer");
            p = new NuPlayerDriver;
            break;
        case TEST_PLAYER:
            ALOGV("Create Test Player stub");
            p = new TestPlayerStub();
            break;
       case   AAH_RX_PLAYER:
            ALOGV(" create A@H RX Player");
            p = createAAH_RXPlayer();
            break;
        case  AAH_TX_PLAYER:
            ALOGV(" create A@H TX Player");
            p = createAAH_TXPlayer();
            break;
#ifdef BUILD_WITH_MST
        case MST_PLAYER:
            ALOGV(" create MstPlayer");
            p = new MstPlayer;
            break;
#endif
        default:
            ALOGE("Unknown player type: %d", playerType);
            return NULL;
    }

 当然也能够把上面的创建播放器对象的代码放到一个工厂类中。

ANDROID系统中的PhoneFactory类就是一个简单工厂类的採用,该类提供了makeDefaultPhonesgetGsmPhonegetCdmaPhonegetDefaultPhonemakeSipPhone等工厂函数来创建和获得不同类型的Phone对象。

以上的简单工厂模式尽管能够在一处改动代码,但还是不满足“开闭设计原则”,也不满足针对接口编程的设计原则,因此在功能扩展时还是须要改动相关代码。

PhoneFactory工厂类还存在一个问题: 为了创建不同类型的Phone对象须要调用PhoneFactory工厂类的不同的工厂函数,尽管它们创建的Phone对象都是Phone的子类。

为了解决上面的简单工厂模式的问题。就须要採用另外的两个工厂模式:工厂方法和抽象工厂,一个採用了类继承的方式,一个採用了对象组合的方式。

2 工厂模式之工厂方法

工厂方法模式通过在要创建对象的共同父类中定义一个公共抽象接口来返回详细类创建的对象。该接口返回的详细对象实际在详细类的实现公共抽象接口的创建函数中创建。

 意图:在抽象类定义一个用于创建对象的接口。让详细类创建详细的对象。

工厂方法的UML结构类图为:

ANDROID 中设计模式的採用--创建型模式[通俗易懂]

ANDROID系统的媒体路由框架中的MediaRouteProvider类就是工厂方法模式的採用。

ANDROID 中设计模式的採用--创建型模式[通俗易懂]


抽象类MediaRouteProvider中提供了一个创建RouteController对象的公共接口onCreateRouteController,用来返回一个MediaRouteProvider.RouteController对象,MediaRouteProvider.RouteController的详细对象实际由MediaRouteProvider的详细派生类在其onCreateRouteController函数中负责创建。如MediaRouteProvider的派生类RegisteredMediaRouteProvider在其onCreateRouteController函数中创建了一个详细类型为RegisteredMediaRouteProvider.ControllerMediaRouteProvider.RouteController对象,MediaRouteProvider的间接派生类SystemMediaRouteProvider.LegacyImplSystemMediaRouteProvider.JellybeanImpl在各自的onCreateRouteController函数中分别创建了派生于MediaRouteProvider.RouteController的两个详细对象:SystemMediaRouteProvider.DefaultRouteControllerSystemMediaRouteProvider.SystemRouteController


3工厂模式之抽象工厂

抽象工厂模式是通过实现一个派生于抽象工厂的详细工厂来负责创建详细的产品或产品系列。抽象工厂模式能够通过实现不同的详细工厂来创建不同的产品或系列,也能够通过详细工厂的不同方法来创建不同的产品。而用户仅仅与抽象工厂打交道。而不关心哪个工厂创建了详细产品。

抽象工厂模式的意图是提供一个创建一系列相关或依赖的对象的接口,用户能够通过该接口创建一系列相关的对象。

ANDROID 中设计模式的採用--创建型模式[通俗易懂]


在最新版本号的ANDROID系统中的媒体框架中上面的媒体播放器的创建就採用了抽象工厂模式。

类图例如以下:

ANDROID 中设计模式的採用--创建型模式[通俗易懂]


当中MediaPlayerFactoryMediaPlayerFactory:IFactory的客户。MediaPlayerFactory通过其包括的抽象工厂MediaPlayerFactory:IFactory的抽象接口createPlayer来创建不同的播放器。每种详细的播放器由每个详细的工厂来负责创建。如StagefrightPlayer播放器由StagefrightPlayerFactory工厂创建,NuPlayerFactory工厂创建NuPlayerDriver播放器。SonivoxPlayerFactory工厂创建MidiFile播放器。TestPlayerFactory工厂创建用于測试的播放器TestPlayerStub。在MediaPlayerFactory类中每种详细的播放器工厂须要採用MediaPlayerFactoryregisterFactory_lregisterFactory函数登记到MediaPlayerFactory类中。以便MediaPlayerFactory类在其工厂方法中可以依据不同的播放类型获得详细的播放工厂来创建详细类型的播放器。

抽象工厂与工厂方法模式的关键差别是:抽象工厂须要创建派生自抽象工厂的详细的工厂。通过详细工厂对象的实例方法来创建详细的产品,工厂对象的责任就是创建详细的产品;而工厂方法模式是提供一个框架,产品的创建是通过要创建产品的子类中的一个工厂方法来完毕,创建产品仅仅是子类的诸多责任中的一项任务。

生成器

有时对象的创建须要採用分步骤来完毕。这时就能够採用生成器模式,UML类图例如以下:

ANDROID 中设计模式的採用--创建型模式[通俗易懂]

ANDROID系统中也存在大量的生成器模式的採用。

AlertDialogUriNotification等对象的创建。例如以下是AlertDialog对象的创建样例。

  AlertDialog dialog = new AlertDialog.Builder(mContext)            .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title))            .setView(textEntryView)            .setPositiveButton(r.getString(R.string.ok), null)            .create();

5、原形

假设须要通过克隆已有的对象来创建新的对象,就要採用原形模式。UML类图例如以下:

ANDROID 中设计模式的採用--创建型模式[通俗易懂]


android系统中全部实现Cloneable接口的类都支持採用原形模式创建其对象,如IntentAnimationBundleComponentNameEvent等对象。

例如以下样例为Intent对象採用原形模式创建其对象的代码片断:

 /**
     * Copy constructor.
     */
    public Intent(Intent o) {
        this.mAction = o.mAction;
        this.mData = o.mData;
        this.mType = o.mType;
        this.mPackage = o.mPackage;
        this.mComponent = o.mComponent;
        this.mFlags = o.mFlags;
        if (o.mCategories != null) {
            this.mCategories = new ArraySet<String>(o.mCategories);
        }
        if (o.mExtras != null) {
            this.mExtras = new Bundle(o.mExtras);
        }
        if (o.mSourceBounds != null) {
            this.mSourceBounds = new Rect(o.mSourceBounds);
        }
        if (o.mSelector != null) {
            this.mSelector = new Intent(o.mSelector);
        }
        if (o.mClipData != null) {
            this.mClipData = new ClipData(o.mClipData);
        }
    }

    @Override
    public Object clone() {
        return new Intent(this);
    }

6 单件模式

假设在一个进程中某个类仅仅须要创建一个实例,就须要採用单件模式,类图例如以下:

ANDROID 中设计模式的採用--创建型模式[通俗易懂]

android系统中,单件模式也普遍採用,以便维持一个进程内的某个类的唯一实例。

如很多硬件相关的系统服务管理类和服务:ServiceManagerSensorManagerWindowManagerGlobalWallpaperManagerAccessibilityManagerUserManagerServiceDownloadManagerBatteryServiceConnectivityManager等。

例如以下代码採用单件模式获得ServiceManager类的单件实例。

private static IServiceManager sServiceManager;
private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

                                      版权全部。请转载时尊重版权清楚注明出处和链接,谢谢!



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116311.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号