Mixin
本文讨论C++中的mixin。
为什么需要mixin?
1、code reuse
mixin最大的好处就是code reuse;
a、mixin常见功能、behavior
对于一些常见功能,比如factory、singleton、clone等,它们的实现模式是非常类似的,为了促进code reuse,使用mixin来将这些概念给予给子类;
b、Requiring-or-Prohibiting
参见"Requiring-or-Prohibiting"相关章节;
实现方式
Mixin from above
下面是一些实现方式:
1) CRTR + inheritance
Mixin from below
1、Parameterized Base Class,参见相关章节;
Summary
1、上述两种实现方式,都需要使用inheritance。
2、在文章 fluentcpp Mixin Classes: The Yang of the CRTP 中,对两者有一定的对比,下面是一个非常形象的图,这篇文章收录在 "Parameterized-Base-Class" 章节了。
Application
1) Singleton mixin: C++\Pattern\Singleton\Singleton-mixin
2) Factory mixin: C++\Pattern\Factory
3、......
c2 Mixins For Cee Plus Plus
In the context of C++ [CeePlusPlus] the term mixin is usually used to match BjarneStroustrup's definition:
A class that provides some - but not all - of the implementation for a virtual base class is often called a "mixin".
You can for example have a virtual abstract base class that defines the interfaces for the import and export of values and a flock of derived classes that implement different means to either export or import, but not both. Then you can combine these second-layer classes to form different concrete classes.
Mix in from above and Mix in from below
I believe that it's possible to MixIn from above (parent classes) or MixIn from below (AbstractSubclasses). The above example shows an example of MixIn from the parent classes through MultipleInheritance. For CeePlusPlus, AbstractSubclasses written by UsingTemplates.
Examples for MixIn through AbstractSubclass
The following code implements the SingletonPattern
template<class SingletonClass>
class Singleton: public SingletonClass
{
public:
/** Singleton creation function */
static Singleton& instance()
{
if (_instance.get() == NULL)
{
_instance = auto_ptr<Singleton<SingletonClass> >(new Singleton);
assert(_instance.get() != NULL);
}
return *_instance;
}
protected:
/** Singleton instance holder */
static auto_ptr<Singleton<SingletonClass> > _instance;
};
/** static instance definition */
template<class SingletonClass> auto_ptr<Singleton<SingletonClass> > Singleton<SingletonClass>::_instance;
If we have a class called MyClass
:
class MyClass
{
public:
virtual void bar();
virtual ~MyClass();
protected:
MyClass();
};
The constructor can either be public or protected depending on the need. A protected constructor can ensure that the class will only be possible to be constructed by subclasses in this case the Singleton MixIn.
The MixIn can be used like:
void foo()
{
Singleton<MyClass>::instance().bar();
}
or
class SingletonMyClass: public Singleton<MyClass>
{
};
void foo()
{
SingletonMyClass::instance().bar();
}
The STL's auto_ptr
is used to ensure proper destruction. In this example, the abstract method this MixIn requires from the parent class is the default constructor. The disadvantage is that it is harder to pass parameters through constructor, but the advantage is OnceAndOnlyOnce because any class can be a singleton by mixing in the AbstractSubclass without rewriting the same code.