您的位置:首页 > 其它

工厂模式

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.h
BufferProviders.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);
...
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: