1 什么是工厂模式?
以下摘自维基百科
工厂方法模式(英语:Factorymethod pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”
创建一个对象常常需要复杂的过程,所以不适合包含在一个复合对象中。创建对象可能会导致大量的重复代码,可能会需要复合对象访问不到的信息,也可能提供不了足够级别的抽象,还可能并不是复合对象概念的一部分。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。
对象创建中的有些过程包括决定创建哪个对象、管理对象的生命周期,以及管理特定对象的创建和销毁的概念。
2 从理论到实际
Android中的MediaPlayerFactory是经典的简单工厂模式, 它是这么定义的:
class MediaPlayerFactory {
public:
class IFactory {
……
};
static status_t registerFactory(IFactory* factory, player_type type);
static void unregisterFactory(player_type type);
private:
typedef KeyedVector<player_type, IFactory*> tFactoryMap;
static tFactoryMap sFactoryMap;
};
MediaPlayerFactory有一个map即sFactoryMap来存储不同种类的Factory,包括StagefrightPlayerFactory,NuPlayerFactory,SonivoxPlayerFactory,TestPlayerFactory,如果有特殊需要,也可以定义一个新的Factory添加进来。
每个Factory都实现了于IFactory的接口,其中最重要的是ScoreFactory和CreatePlayer
class IFactory {
public:
virtual ~IFactory() { }
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
const char* /*url*/,
float/*curScore*/) { return 0.0; }
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
int /*fd*/,
int64_t/*offset*/,
int64_t/*length*/,
float/*curScore*/) { return 0.0; }
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
constsp<IStreamSource> &/*source*/,
float/*curScore*/) { return 0.0; }
virtual sp<MediaPlayerBase> createPlayer() = 0;
};
应用程序一般会调用MediaPlayerFactory的getPlayerType函数
player_typeMediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
const char* url) {
GET_PLAYER_TYPE_IMPL(client, url);
}
在GET_PLAYER_TYPE_IMPL中,实际上就是根据url给sFactoryMap中的各个Factory打分,然后拿到得分最高的那个Factory。
#define GET_PLAYER_TYPE_IMPL(a...) \
Mutex::Autolock lock_(&sLock); \
player_type ret = STAGEFRIGHT_PLAYER; \
float bestScore = 0.0; \
for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
IFactory* v = sFactoryMap.valueAt(i); \
float thisScore; \
CHECK(v != NULL); \
thisScore = v->scoreFactory(a, bestScore); \
if (thisScore > bestScore) { \
ret = sFactoryMap.keyAt(i); \
bestScore = thisScore; \
} \
} \
if (0.0 == bestScore) { \
ret = getDefaultPlayerType(); \
} \
return ret;
得到对应的Factory后,调用这个它的createPlayer方法,获得对应的Player
class StagefrightPlayerFactory :
public MediaPlayerFactory::IFactory {
public:
virtual floatscoreFactory(const sp<IMediaPlayer>& /*client*/,
}
virtual sp<MediaPlayerBase> createPlayer() {
ALOGV(" create StagefrightPlayer");
return new StagefrightPlayer();
}
};
而Player在初始化的时候,创建了另一个真正干活的player就是AwesomePlayer。
StagefrightPlayer::StagefrightPlayer()
: mPlayer(new AwesomePlayer) {
ALOGV("StagefrightPlayer");
mPlayer->setListener(this);
}
3 总结
1. 当调用者需要一个产品时,直接传递一个参数给工厂,让工厂生产不同的产品。
2. 这些产品实现了同样的接口。
3. 调用者无需了解细节,只需要提要求(传参数)给工厂即可。