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类就是一个简单工厂类的採用,该类提供了makeDefaultPhones、getGsmPhone、getCdmaPhone、getDefaultPhone、makeSipPhone等工厂函数来创建和获得不同类型的Phone对象。
以上的简单工厂模式尽管能够在一处改动代码,但还是不满足“开闭设计原则”,也不满足针对接口编程的设计原则,因此在功能扩展时还是须要改动相关代码。
PhoneFactory工厂类还存在一个问题: 为了创建不同类型的Phone对象须要调用PhoneFactory工厂类的不同的工厂函数,尽管它们创建的Phone对象都是Phone的子类。
为了解决上面的简单工厂模式的问题。就须要採用另外的两个工厂模式:工厂方法和抽象工厂,一个採用了类继承的方式,一个採用了对象组合的方式。
2 工厂模式之工厂方法
工厂方法模式通过在要创建对象的共同父类中定义一个公共抽象接口来返回详细类创建的对象。该接口返回的详细对象实际在详细类的实现公共抽象接口的创建函数中创建。
意图:在抽象类定义一个用于创建对象的接口。让详细类创建详细的对象。
工厂方法的UML结构类图为:
在ANDROID系统的媒体路由框架中的MediaRouteProvider类就是工厂方法模式的採用。
抽象类MediaRouteProvider中提供了一个创建RouteController对象的公共接口onCreateRouteController,用来返回一个MediaRouteProvider.RouteController对象,MediaRouteProvider.RouteController的详细对象实际由MediaRouteProvider的详细派生类在其onCreateRouteController函数中负责创建。如MediaRouteProvider的派生类RegisteredMediaRouteProvider在其onCreateRouteController函数中创建了一个详细类型为RegisteredMediaRouteProvider.Controller的MediaRouteProvider.RouteController对象,MediaRouteProvider的间接派生类SystemMediaRouteProvider.LegacyImpl和SystemMediaRouteProvider.JellybeanImpl在各自的onCreateRouteController函数中分别创建了派生于MediaRouteProvider.RouteController的两个详细对象:SystemMediaRouteProvider.DefaultRouteController和SystemMediaRouteProvider.SystemRouteController。
3工厂模式之抽象工厂
抽象工厂模式是通过实现一个派生于抽象工厂的详细工厂来负责创建详细的产品或产品系列。抽象工厂模式能够通过实现不同的详细工厂来创建不同的产品或系列,也能够通过详细工厂的不同方法来创建不同的产品。而用户仅仅与抽象工厂打交道。而不关心哪个工厂创建了详细产品。
抽象工厂模式的意图是提供一个创建一系列相关或依赖的对象的接口,用户能够通过该接口创建一系列相关的对象。
![]()
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvR29vSG9uZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center">
在最新版本号的ANDROID系统中的媒体框架中上面的媒体播放器的创建就採用了抽象工厂模式。
类图例如以下:
当中MediaPlayerFactory为MediaPlayerFactory:IFactory的客户。MediaPlayerFactory通过其包括的抽象工厂MediaPlayerFactory:IFactory的抽象接口createPlayer来创建不同的播放器。每种详细的播放器由每个详细的工厂来负责创建。如StagefrightPlayer播放器由StagefrightPlayerFactory工厂创建,NuPlayerFactory工厂创建NuPlayerDriver播放器。SonivoxPlayerFactory工厂创建MidiFile播放器。TestPlayerFactory工厂创建用于測试的播放器TestPlayerStub。在MediaPlayerFactory类中每种详细的播放器工厂须要採用MediaPlayerFactory的registerFactory_l或registerFactory函数登记到MediaPlayerFactory类中。以便MediaPlayerFactory类在其工厂方法中可以依据不同的播放类型获得详细的播放工厂来创建详细类型的播放器。
抽象工厂与工厂方法模式的关键差别是:抽象工厂须要创建派生自抽象工厂的详细的工厂。通过详细工厂对象的实例方法来创建详细的产品,工厂对象的责任就是创建详细的产品;而工厂方法模式是提供一个框架,产品的创建是通过要创建产品的子类中的一个工厂方法来完毕,创建产品仅仅是子类的诸多责任中的一项任务。
4 生成器
有时对象的创建须要採用分步骤来完毕。这时就能够採用生成器模式,UML类图例如以下:
在ANDROID系统中也存在大量的生成器模式的採用。
如AlertDialog、Uri、Notification等对象的创建。例如以下是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系统中全部实现Cloneable接口的类都支持採用原形模式创建其对象,如Intent、Animation、Bundle、ComponentName、Event等对象。
例如以下样例为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系统中,单件模式也普遍採用,以便维持一个进程内的某个类的唯一实例。
如很多硬件相关的系统服务管理类和服务:ServiceManager、SensorManager、WindowManagerGlobal、WallpaperManager、AccessibilityManager、UserManagerService、DownloadManager、BatteryService、ConnectivityManager等。
例如以下代码採用单件模式获得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;
}版权全部。请转载时尊重版权清楚注明出处和链接,谢谢!
ANDROID 中设计模式的採用--创建型模式的更多相关文章
- 6、单例模式 Singleton模式 只有一个实例 创建型模式
1.了解Singleton模式 程序在运行时,通常都会生成很多实例.例如,表示字符串的java . lang . string类的实例与字符串是- -对- -的关系,所以当有1000个字符串的时候,会 ...
- 工厂方法模式——创建型模式02
1. 简单工厂模式 在介绍工厂方法模式之前,先介绍一下简单工厂模式.虽然简单工厂模式不属于GoF 23种设计模式,但通常将它作为学习其他工厂模式的入门,并且在实际开发中使用的也较为频繁. (1 ...
- 设计模式学习之简单工厂(Simple Factory,创建型模式)(1)
简单工厂(Simple Factory,创建型模式) 第一步: 比如我们要采集苹果和香蕉,那么我们需要创建一个Apple类和Banana类,里面各自有采集方法get(),然后通过main方法进行调用, ...
- .NET设计模式(7):创建型模式专题总结(Creational Pattern)(转)
概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独立于如何创建.组合和表示它的那些对象.本文对五种常用创建型模式进行了比较,通过一个游戏开发场景的例子来说该如何使用创建型模 ...
- .NET设计模式(7):创建型模式专题总结(Creational Pattern)
):创建型模式专题总结(Creational Pattern) 创建型模式专题总结(Creational Pattern) --.NET设计模式系列之七 Terrylee,2006年1月 转载: ...
- Java 23种设计模式详尽分析与实例解析之一--创建型模式
面向对象的设计原则 常用的面向对象设计原则包括7个,这些原则并不是独立存在的,它们相互依赖.互为补充. Java设计模式 创建型模式 简单工厂模式 模式动机: 考虑一个简单的软件应用场景,一个软件系统 ...
- [C#]设计模式-抽象工厂-创建型模式
介绍了简单工厂与工厂方法之后,现在我们来看一下工厂三兄弟的最后一个 -- 抽象工厂. 那什么是抽象工厂呢? 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相 ...
- NET设计模式 第二部分 创建型模式(6):创建型模式专题总结(Creational Pattern)
创建型模式专题总结(Creational Pattern) ——.NET设计模式系列之七 Terrylee,2006年1月 概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统 ...
- 设计模式GOF23(创建型模式)
• 创建型模式: 单例模式.工厂模式.抽象工厂模式.建造者模式.原型模式. • 结构型模式: –适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式. • 行为型模式: 模 ...
随机推荐
- BZOJ 3477: [Usaco2014 Mar]Sabotage( 二分答案 )
先二分答案m, 然后对于原序列 A[i] = A[i] - m, 然后O(n)找最大连续子序列和, 那么此时序列由 L + mx + R组成. L + mx + R = sum - n * m, s ...
- C 语言学习 之搭建环境和熟悉命令
Open Terminal 打开终端To run a command as administrator (user "root"), use "sudo <comm ...
- 在CentOS下源码安装 Xen并搭建Windows虚拟机
前言 首先要感谢xing的帮助,在他的指导之下才完成环境的搭建,本文档的部分内容来自他的文档.另外,还要感谢——互联网. 1. 环境介绍 Linux: CentOS 6.3 Xen: Xe ...
- Qt新建线程的方法(有QRunnable,QThreadPool,moveToThread和QtConcurrent的例子)
看了不少Qt线程的东西,下面总结一下Qt新建一个线程的方法. 一.继承QThread 继承QThread,这应该是最常用的方法了.我们可以通过重写虚函数void QThread::run ()实现我们 ...
- 【译】在ASP.NET中创建PDF-iTextSharp起步
原文 [译]在ASP.NET中创建PDF-iTextSharp起步 .Net framework 中自身并不包含可以和pdf打交道的方法.所以,当你需要你的ASP.Net Web应用程序中包含创建或与 ...
- SQL之单行函数
单行函数语法: function name(column|expression,[arg1,arg2,...]) 参数说明: function name:函数名称 column:数据库列名 expre ...
- 【floyd】HDU 1874 畅通project续
之后的题解偏重有用/总结性质,尽量理解算法本身而不是题,时间复杂度什么的也能够放放. 非常久之前做过这个题,当时使用dijkstra做的,关于几个最短路算法,分类的话能够分为下面几种. 1.单源最短路 ...
- 史上最强Android 开启照相或者是从本地相册选中一张图片以后先裁剪在保存并显示的讲解附源码
整个程序的布局很简单 只在一个垂直方向上的线性布局里面有俩个按钮(Button)和一个显示图片的控件(ImageView)这里就不给出这部分的代码了 1.是打开系统的相册 Intent alb ...
- 总线接口与计算机通信(三)UART起止式异步通用串行数据总线
串口简介 1. 什么是串口? 串口是计算机上一种非常通用的设备通信的协议.串口通信的概念非常简单,串口按位(bit) 发送和接收字节.尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送 ...
- NProxy——Mac和Linux平台下的Fiddler
Fiddler 相信大家,尤其是前端工程师们都知道. 用它的文件替换功能,将线上的静态资源文件(JS.CSS.图片)替换为本地相应的文件,来调试线上(代码都被压缩过)UI的问题.的确是一神器.(相比, ...