FACTORY模式允许我们只依赖抽象接口就能创建出具体对象的实例。所以,开发期间如果具体类是高度易变的,那么该模式就很适合。
1. 简单工厂
简单工厂的一个特点就是工厂类必须知道所有具体厂品的实现,根据传进来的参数通过if/else判断创建哪个具体厂品。这样其他地方不需要创建具体厂品。做到了职责的分离。如果要创建对象只需要通过这个工厂类,这个工厂类通常由main或者由一个隶属于main的初始化函数创建出来。但这也意味着如果要增加新的厂品类就必须改变工厂类,从而改变所有使用工厂类的程序。
2. FACTORY METHOD
工厂方法模式提出得主要目的是把一个类的实例化延迟到其子类。即程序中知道某个地方将使用这个厂品类等级结构中的一个,但不知道哪个具体厂品将被创建(由用户指定),一个解决方法就是用一个抽象工厂类代替,它返回一个抽象厂品。然后运行时让工厂子类决定实例化哪个厂品。gof中的工厂类并不是纯粹地为了创建对象,工厂类同时还带有其他函数,这些函数使用被创建出来的对象,带有很多的商业逻辑。也许这就是FACTORY METHOD中的METHOD的意思。
另外它还附带了一个好处就是因为它是针对一组继承的厂品等级结构,构造出一一对应的工厂等级结构。这样就不再像简单工厂那样由一个工厂负责所有具体产品的创建,而是将创建工作交给与那个具体厂品相应的工厂去做,这使得可以允许系统在不修改工厂角色的情况下引进新产品。但是这里有一个问题,就是如何指定由哪个具体工厂来创建具体厂品,是不是把具体厂品的创建逻辑转移到具体工厂的创建上来了呢?这个问题的解决方法之一是通过配置文件解决。利用反射根据配置文件可以不要重新编译得到需要的具体工厂,而以后要改变需要的具体工厂只要需要改变配置文件,而不需要重新编译。
<appSettings>
<add key=" concreteA" value=" concreteAFactory" />
<add key=" concreteB" value=" concretbBFactory" />
</appSettings>
用到配置文件和反射,这里就有一个新的问题,就是到底我们需要这么多工厂吗?其实我们定义一个工厂,然后它可以根据配置文件利用反射返回具体的厂品类不是也可以达到需求?这是对的。我认为之所以有相应的厂品等级结构主要原因是没使用反射机制,gof用到的是C++,是不支持反射的,所以他们用的是和厂品类有相同等级结构的工厂,经过后人的模仿因此在JAVA,.NET中也出现了这种情况。这里重新强调一下其实工厂方法模式的意图并不是解决灵活地引进新的厂品类,而是使一个类的实例化延迟到其子类。(有些模式的书籍说工厂方法和简单工厂的区别就是为了引进新的厂品而不用修改原有的代码,这样只是把构建的逻辑从厂品转移到工厂,即把具体产品的创建逻辑封装到工厂类中).
学习模式并不是说要把自己的思想尽力向专家的方案上靠。但是专家的成果往往有很成熟的理由,我们不能误解它。
3. 抽象工厂
说简单点就是N选1,一个应用程序根据自己所在的平台或环境在这N套类中选一套使用。如下图,由于每套类都是实现相同的功能,因此它们之间的类也几乎是一一对应,比如UnixControl这套类中UnixButton就和Win这套类中的WinButton相对应。因此UnixButton和WinButton都可以从Button派生。
适用性:
1. 一个系统要独立于它的产品的创建,组合和表示。
2. 一个系统要由多个产品系列中的一个来配置。
3. 当你要强调一系列相关产品对象的设计以便进行联合使用时。
Ogre里面是实现工厂的方法是:
template< typename T > class FactoryObj { public: virtual ~FactoryObj() {}; /** Returns the factory type. @return The factory type. */ virtual const String& getType() const = 0; /** Creates a new object. @param name Name of the object to create @return An object created by the factory. The type of the object depends on the factory. */ virtual T* createInstance( const String& name ) = 0; /** Destroys an object which was created by this factory. @param ptr Pointer to the object to destroy */ virtual void destroyInstance( T* ) = 0; };
所有的工厂都要从这个类派生。它定义了所有工厂都要实现的方法。因为使用了模板:
virtual T* createInstance( const String& name ) = 0;
返回的就是各系列的类型。比如下图ArchiveFactory系列工厂就是返回Archive厂品。
摘自:http://www.cnblogs.com/sweetdream/archive/2006/01/09/313953.html
原文:http://www.cnblogs.com/forzhongyou/p/3907364.html