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工厂模式之抽象工厂
抽象工厂模式是通过实现一个派生于抽象工厂的具体工厂来负责创建具体的产品或产品系列。抽象工厂模式可以通过实现不同的具体工厂来创建不同的产品或系列,也可以通过具体工厂的不同方法来创建不同的产品。而用户只与抽象工厂打交道,而不关心哪个工厂创建了具体产品。
抽象工厂模式的意图是提供一个创建一系列相关或依赖的对象的接口,用户可以通过该接口创建一系列相关的对象。
在最新版本的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 中设计模式的采用--创建型模式的更多相关文章
- NET设计模式 第二部分 创建型模式(6):创建型模式专题总结(Creational Pattern)
创建型模式专题总结(Creational Pattern) ——.NET设计模式系列之七 Terrylee,2006年1月 概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统 ...
- 抽象工厂模式(abstract)创建型模式
(一)简单工厂模式? 现在的学习是面向对象面向接口的,但是执行时的操作需要实例化后的对象.随着我们需要的类的增加,我们就需要把这些共同的东西提取出来,放在一个抽象类中,让这些子类来继承抽象类.当我们调 ...
- 设计模式学习之建造者模式(Builder,创建型模式)(6)
假如我们需要建造一个房子,并且我们也不知道如何去建造房子,所以就去找别人帮我们造房子 第一步: 新建一个房子类House,里面有房子该有的属性,我们去找房子建造者接口HouseBuilder,我们要建 ...
- 设计模式学习之原型模式(Prototype,创建型模式)(5)
通过序列化的方式实现深拷贝 [Serializable] public class Person:ICloneable { public string Name { get; set; } publi ...
- 设计模式-抽象工厂模式(AbstractFactory)(创建型模式)
//以下代码来源: 设计模式精解-GoF 23种设计模式解析附C++实现源码 //Product.h #pragma once class AbstractProductA { public: vir ...
- Java 23种设计模式详尽分析与实例解析之一--创建型模式
面向对象的设计原则 常用的面向对象设计原则包括7个,这些原则并不是独立存在的,它们相互依赖.互为补充. Java设计模式 创建型模式 简单工厂模式 模式动机: 考虑一个简单的软件应用场景,一个软件系统 ...
- 设计模式GOF23(创建型模式)
• 创建型模式: 单例模式.工厂模式.抽象工厂模式.建造者模式.原型模式. • 结构型模式: –适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式. • 行为型模式: 模 ...
- 第26章 创建型模式大PK
26.1 工厂方法模式 VS 建造者模式 26.1.1 按工厂方法建造超人 (1)产品:两类超人,成年超人和未成年超人. (2)工厂:这里选择简单工厂 [编程实验]工厂方法建造超人 //创建型模式大P ...
- .NET设计模式(7):创建型模式专题总结(Creational Pattern)(转)
概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独立于如何创建.组合和表示它的那些对象.本文对五种常用创建型模式进行了比较,通过一个游戏开发场景的例子来说该如何使用创建型模 ...
随机推荐
- Hadoop 伪分布式安装、运行测试例子
1. 配置linux系统环境 centos 6.4 下载地址:http://pan.baidu.com/s/1geoSWuv[VMWare专用CentOS.rar](安装打包好的VM压缩包) 并配置虚 ...
- 将树形递归转换为loop
class Stack(object): def __init__(self,**kwargs): self.__dict__.update(kwargs) def __str__(self): re ...
- Java异常处理机制难点解惑-用代码说话
是否需要看这篇文章? 下面的例子中,如果正常执行返回值多少? 如果出现了ArithmeticException返回值多少? 如果出现非ArithmeticException(如NullPointerE ...
- BI Publisher(rtf)模板开发语法大全
Rtf模板开发例如背景,纹理分栏等等功能都能用word工具实现不再具体总结大家可以参考word教程..... 一.组 定义一个组的目的是告诉XMLPublisher对重复的数据行进行循环显示,也就 ...
- mysql进阶(二十六)MySQL 索引类型(初学者必看)
mysql进阶(二十六)MySQL 索引类型(初学者必看) 索引是快速搜索的关键.MySQL 索引的建立对于 MySQL 的高效运行是很重要的.下面介绍几种常见的 MySQL 索引类型. 在数 ...
- Android事件总线EventBus详解
顾名思义,AndroidEventBus是一个Android平台的事件总线框架,它简化了Activity.Fragment.Service等组件之间的交互,很大程度上降低了它们之间的耦合,使我们的代码 ...
- [ExtJS5学习笔记]第八节 Extjs5的Ext.toolbar.Toolbar工具条组件及其应用
本文地址:http://blog.csdn.net/sushengmiyan/article/details/38515499 本文作者:sushengmiyan ------------------ ...
- 对N各集合中的任意元素进行排列组合问题
小李去市场买菜,有蔬菜(茄子.黄瓜.大白菜...等k中素菜),和肉类(牛肉,羊肉,鸡肉...等m种荤菜),及点心(麻饼,桃酥,枣花...等n中点心),现在老婆要求每天一荤一素一点心 并且每天的样式要尽 ...
- SpringMVC源码分析--容器初始化(五)DispatcherServlet
上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...
- Servlet之Listener监听器
Servlet2.5规范共有8中Listener接口,6种Event类型 ServletContextListener接口 [接口方法] contextInitialized()与 contextDe ...