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. 调用者无需了解细节,只需要提要求(传参数)给工厂即可。