////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Wesley Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#ifndef LOKI_ABSTRACTFACTORY_INC_
#define LOKI_ABSTRACTFACTORY_INC_
// $Id: AbstractFactory.h 771 2006-10-27 18:05:03Z clitte_bbt $
#include "Typelist.h"
#include "Sequence.h"
#include "TypeManip.h"
#include "HierarchyGenerators.h"
#include <cassert>
/**
* \defgroup FactoriesGroup Factories
* \defgroup AbstractFactoryGroup Abstract Factory
* \ingroup FactoriesGroup
* \brief Implements an abstract object factory.
*/
/**
* \class AbstractFactory
* \ingroup AbstractFactoryGroup
* \brief Implements an abstract object factory.
*/
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template AbstractFactoryUnit
// The building block of an Abstract Factory
////////////////////////////////////////////////////////////////////////////////
template <class T>
class AbstractFactoryUnit
{
public:
virtual T* DoCreate(Type2Type<T>) = 0;
virtual ~AbstractFactoryUnit() {}
};
////////////////////////////////////////////////////////////////////////////////
// class template AbstractFactory
// Defines an Abstract Factory interface starting from a typelist
////////////////////////////////////////////////////////////////////////////////
template
<
class TList,
template <class> class Unit = AbstractFactoryUnit
>
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
{
public:
typedef TList ProductList;
template <class T> T* Create()
{
Unit<T>& unit = *this;
return unit.DoCreate(Type2Type<T>());
}
};
////////////////////////////////////////////////////////////////////////////////
// class template OpNewFactoryUnit
// Creates an object by invoking the new operator
////////////////////////////////////////////////////////////////////////////////
template <class ConcreteProduct, class Base>
class OpNewFactoryUnit : public Base
{
typedef typename Base::ProductList BaseProductList;
protected:
typedef typename BaseProductList::Tail ProductList;
public:
typedef typename BaseProductList::Head AbstractProduct;
ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
{
return new ConcreteProduct;
}
};
////////////////////////////////////////////////////////////////////////////////
// class template PrototypeFactoryUnit
// Creates an object by cloning a prototype
// There is a difference between the implementation herein and the one described
// in the book: GetPrototype and SetPrototype use the helper friend
// functions DoGetPrototype and DoSetPrototype. The friend functions avoid
// name hiding issues. Plus, GetPrototype takes a reference to pointer
// instead of returning the pointer by value.
////////////////////////////////////////////////////////////////////////////////
template <class ConcreteProduct, class Base>
class PrototypeFactoryUnit : public Base
{
typedef typename Base::ProductList BaseProductList;
protected:
typedef typename BaseProductList::Tail ProductList;
public:
typedef typename BaseProductList::Head AbstractProduct;
PrototypeFactoryUnit(AbstractProduct* p = 0)
: pPrototype_(p)
{}
template <class CP, class Base1>
friend void DoGetPrototype(const PrototypeFactoryUnit<CP, Base1>& me,
typename Base1::ProductList::Head*& pPrototype);
template <class CP, class Base1>
friend void DoSetPrototype(PrototypeFactoryUnit<CP, Base1>& me,
typename Base1::ProductList::Head* pObj);
template <class U>
void GetPrototype(U*& p)
{ return DoGetPrototype(*this, p); }
template <class U>
void SetPrototype(U* pObj)
{ DoSetPrototype(*this, pObj); }
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
{
assert(pPrototype_);
return pPrototype_->Clone();
}
private:
AbstractProduct* pPrototype_;
};
template <class CP, class Base>
inline void DoGetPrototype(const PrototypeFactoryUnit<CP, Base>& me,
typename Base::ProductList::Head*& pPrototype)
{ pPrototype = me.pPrototype_; }
template <class CP, class Base>
inline void DoSetPrototype(PrototypeFactoryUnit<CP, Base>& me,
typename Base::ProductList::Head* pObj)
{ me.pPrototype_ = pObj; }
////////////////////////////////////////////////////////////////////////////////
// class template ConcreteFactory
// Implements an AbstractFactory interface
////////////////////////////////////////////////////////////////////////////////
template
<
class AbstractFact,
template <class, class> class Creator = OpNewFactoryUnit,
class TList = typename AbstractFact::ProductList
>
class ConcreteFactory
: public GenLinearHierarchy<
typename TL::Reverse<TList>::Result, Creator, AbstractFact>
{
public:
typedef typename AbstractFact::ProductList ProductList;
typedef TList ConcreteProductList;
};
} // namespace Loki
#endif // end file guardian
第九章 抽象工厂
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 定义: 为创建一组相关或者相互依赖的对象提供接口,而且无须指定它们的具体类。 通用的表示形式: ps:图中的1、2...
- 今天和大家分享一下设计模式中的 简单工厂 工厂方法 抽象工厂 1.简单工厂模式(Simple Factory Pa...
- 先开个小头,明天写出来,不逼着自己是不会干活的。 题外话: 首先,设计模式是什么,为什么要用设计模式,设计模式用来...