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(创建型模式)
• 创建型模式: 单例模式.工厂模式.抽象工厂模式.建造者模式.原型模式. • 结构型模式: –适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式. • 行为型模式: 模 ...
随机推荐
- 最新Cocos2d-x3.2开发环境搭建(windows环境下)
原文地址:http://cache.baiducontent.com/c?m=9d78d513d9921cfe05ac837f7d16c067690297634d9dc7150ed58449e3735 ...
- 03-UIKit、VC之间正向反向传值、代理
目录: 一.正向传值 二.反向传值 三.代理模式 回到顶部 正向传值:就是把第一个界面的值传给第二个界面显示,其简单实现方法 1 首先在第一个界面中要有一个textField输入框,一个按钮butto ...
- iTextSharp - 建立PDF文件
原文 iTextSharp - 建立PDF文件 01 using iTextSharp.text; 02 using iTextSharp.text.pdf; 03 ... 04 private vo ...
- cmake手册详解----转
参考链接:http://www.cnblogs.com/coderfenghc/tag/cmake/
- HTML的表单元�
HTML的表单元素 表单元素是同意用户在表单中(比方:文本域,下拉列表,单选框,复选框等等)输入信息的元素 表单标签 文本域(Text Fields) 当用户要在表单中键入字母,数字等内容时,就会用到 ...
- o(n)解决问题:调整数组顺序是奇数位于偶数的前面
问题描述: 输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分 void reOrder(int *a,int len) { if(a==NULL || ...
- while和do while习题
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 练习 { ...
- HDU Wolf and Rabbit
Description There is a hill with n holes around. The holes are signed from 0 to n-1. A rabbit must h ...
- Eclipse用法和技巧十九:eclipse修改workspace
工作中某一个项目的文件一般都在某一个路径,大多数人都习惯固定eclipse的workspace.不过偶尔也有点别的,比如做一个大项目中穿插着做些OJ,或者别的……这个时候当然可以选择在安装一个ecli ...
- const对象默认是static的,而不是extern的
const 和 static 变量,可以放在头文件中 const对象默认是static的,而不是extern的,所以即使放在头文件中声明和定义.多个cpp引用同一个头文件,互相也没有感知,所以不会导致 ...