工厂模式
2015-12-02 13:15
302 查看
工厂模式的概念
概念皆来自wikipedia:工厂方法工厂方法模式(Factory method pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。
什么情况需要工厂模式
创建一个对象常常需要复杂的过程,所以不适合包含在一个复合对象中。创建对象可能会导致大量的重复代码,可能会需要复合对象访问不到的信息,也可能提供不了足够级别的抽象,还可能并不是复合对象概念的一部分。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。创建对象需要大量重复的代码。
创建对象需要访问某些信息,而这些信息不应该包含在复合类中。
创建对象的生命周期必须集中管理,以保证在整个程序中具有一致的行为。
使用工厂模式需要注意什么
对象创建中的有些过程包括决定创建哪个对象、管理对象的生命周期,以及管理特定对象的创建和销毁的概念。以我目前接触的知识面而言,webrtc的跨平台实现方式就是这样的设计模式,Android源码的媒体操作-MediaSource,音频数据操作的-AudioBufferProvider都大量采用了工厂模式。例子
framework/av大量采用了工厂模式,视频的MediaSource,音频的AudioBufferProvider作为工厂的父类被广泛使用。以音频通道、格式、播放率转换为例,理解工厂模式。
此类图依据文件
android-6.0.0_r1/frameworks/av/services/audioflinger/BufferProviders.hBufferProviders.h而画。
1.AudioBufferProvider作为AudioFlinger中大多数音频数据提供者的父类,从设计之初到现在都未有过改变。
class AudioBufferProvider { public: struct Buffer { Buffer() : raw(NULL), frameCount(0) { } union { void* raw; short* i16; int8_t* i8; }; size_t frameCount; }; virtual ~AudioBufferProvider() {} static const int64_t kInvalidPTS = 0x7FFFFFFFFFFFFFFFLL; // <stdint.h> is too painful virtual status_t getNextBuffer(Buffer* buffer, int64_t pts = kInvalidPTS) = 0; virtual void releaseBuffer(Buffer* buffer) = 0; };
2.PassthruBufferProvider添加并实现setBufferProvider接口,通过此接口提供一个AudioBufferProvider作为原始音频数据的来源,用户通过父类方法getNextBuffer获取到处理后的数据。
class PassthruBufferProvider : public AudioBufferProvider { public: PassthruBufferProvider() : mTrackBufferProvider(NULL) { } virtual ~PassthruBufferProvider() { } virtual void reset() { } virtual void setBufferProvider(AudioBufferProvider *p) { mTrackBufferProvider = p; } protected: AudioBufferProvider *mTrackBufferProvider; };
3.CopyBufferProvider,用户调用此对象的getNextBuffer时,先通过mTrackBufferProvider的getNextBuffer获取到数据mBuffer,最后调用copyFrames把mBuffer的数据数据处理,最后把dst数据返回给getNextBuffer。copyFrames是一个抽象接口,需要其他子类来实现。
class CopyBufferProvider : public PassthruBufferProvider { public: CopyBufferProvider(size_t inputFrameSize, size_t outputFrameSize, size_t bufferFrameCount); virtual ~CopyBufferProvider(); virtual status_t getNextBuffer(Buffer *buffer, int64_t pts); virtual void releaseBuffer(Buffer *buffer); virtual void reset(); virtual void copyFrames(void *dst, const void *src, size_t frames) = 0; private: AudioBufferProvider::Buffer mBuffer; };
4.DownmixerBufferProvider: provide position dependent downmixing by an Audio Effect.(不过仅仅支持AUDIO_FORMAT_PCM_16_BIT的位宽,通过AudioMixer.cpp可以看出)
void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames) { mDownmixConfig.inputCfg.buffer.frameCount = frames; mDownmixConfig.inputCfg.buffer.raw = const_cast<void *>(src); mDownmixConfig.outputCfg.buffer.frameCount = frames; mDownmixConfig.outputCfg.buffer.raw = dst; // may be in-place if src == dst. status_t res = (*mDownmixHandle)->process(mDownmixHandle, &mDownmixConfig.inputCfg.buffer, &mDownmixConfig.outputCfg.buffer); ALOGE_IF(res != OK, "DownmixBufferProvider error %d", res); }
5.RemixBufferProvider: perform an upmix or downmix to the proper channel count and mask.(upmix和downmix通道)
void RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames) { memcpy_by_index_array(dst, mOutputChannels, src, mInputChannels, mIdxAry, mSampleSize, frames); }
6.ReformatBufferProvider: convert the input data to an acceptable mixer input format type.(音频格式转换)
void ReformatBufferProvider::copyFrames(void *dst, const void *src, size_t frames) { memcpy_by_audio_format(dst, mOutputFormat, src, mInputFormat, frames * mChannelCount); }
7.TimestretchBufferProvider: for time stretching。由于复杂度的问题,它直接继承PassthruBufferProvider去实现工厂模式,而不是继承CopyBufferProvider。
class TimestretchBufferProvider : public PassthruBufferProvider { public: TimestretchBufferProvider(int32_t channelCount, audio_format_t format, uint32_t sampleRate, const AudioPlaybackRate &playbackRate); virtual ~TimestretchBufferProvider(); virtual status_t getNextBuffer(Buffer* buffer, int64_t pts); virtual void releaseBuffer(Buffer* buffer); virtual status_t setPlaybackRate(const AudioPlaybackRate &playbackRate); ... }
相关文章推荐
- linux配置nfs步骤及心得
- 在MyEclipse2015中上传项目到github的步骤
- 伴随ListView、RecyclerView、ScrollView滚动滑入滑出小图标--第三方开源--FloatingActionButton
- iOS音频文件拼接+裁剪(音频文件拼接做了性能优化)
- ZZULIOJ 1400 这不可能是情书吧
- jQuery选择器之基本选择器和层次选择器
- LeetCode---Ugly Number II
- NSNumber和Int的互相转换
- 使用Myeclipse内置Ant编译项目时提醒警告java\lang\Object.class(java\lang:Object.class): 主版本 51 比 50 新,此编译器支持最新的主版本
- centos编译telepresence测试效果
- 百钱买百鸡
- android--RecycleView.Adapter的初体验
- 人工智能(AI)资料大全
- LintCode: Flatten Binary Tree to Linked List
- win7下,vs2013+qt5.3+qwt6.1.2安装配置
- android透明状态栏
- Java开发环境
- NYOJ 463 九九乘法表
- 一个美国人到中国当产品经理的心得:中国App设计真好!
- Activiti学习笔记目录