類型映射假設我有兩套相關類型的,例如Animal
S和他們的Offspring
:在對象工廠
/* Animal types */
struct Animal
{
virtual string getType() const = 0;
};
struct Cat : public Animal
{
virtual string getType() const { return "Cat"; }
};
struct Dog : public Animal
{
virtual string getType() const { return "Dog"; }
};
/* Offspring types */
struct Offspring
{
virtual string getType() const = 0;
};
struct Kitten : public Offspring
{
virtual string getType() const { return "Kitten"; }
};
struct Puppy : public Offspring
{
virtual string getType() const { return "Puppy"; }
};
我想實現一個製造工廠,它給予Animal
將返回一個對象相關Offspring
類型(例如,如果Animal
事實上是Dog
,工廠將返回Puppy
)。
我在實現這樣一個工廠第一次嘗試是這樣的:
// First attempt at OffspringFactory
class OffspringFactory1
{
static Offspring* createKitten() { return new Kitten(); }
static Offspring* createPuppy() { return new Puppy(); }
public:
// Create an Offspring according to the Animal type
static Offspring* getOffspring(const Animal& a)
{
// Static mapping of Animal types to Offspring factory functions
static map<string, Offspring* (*)()> factoryMap;
if (factoryMap.empty())
{
factoryMap["Dog"] = &createPuppy;
factoryMap["Cat"] = &createKitten;
}
// Lookup our Offspring factory function
map<string, Offspring* (*)()>::const_iterator fnIt = factoryMap.find(a.getType());
if (fnIt != factoryMap.end())
return fnIt->second();
else
throw "Bad animal type";
}
};
它工作正常,但我已經使出了基於字符串的映射,而不是純粹基於類型的事。在試圖走向更基於類型的實現移動我來到這個:
// Second attempt at OffspringFactory
class OffspringFactory2
{
// Mapping Animal types to Offspring types
template<typename TAnimal> struct OffspringMapper;
template<>
struct OffspringMapper<Cat> {
typedef Kitten offspring_type;
};
template<>
struct OffspringMapper<Dog> {
typedef Puppy offspring_type;
};
// Factory method
template<typename TAnimal>
static Offspring* create() { return new OffspringMapper<TAnimal>::offspring_type(); }
public:
// Create an Offspring according to the Animal type
static Offspring* getOffspring(const Animal& a)
{
// Static mapping of Animal type strings to Offspring factory functions
static map<string, Offspring* (*)()> factoryMap;
if (factoryMap.empty())
{
factoryMap["Dog"] = &create<Dog>;
factoryMap["Cat"] = &create<Cat>;
}
// Lookup our Offspring factory function
map<string, Offspring* (*)()>::const_iterator fnIt = factoryMap.find(a.getType());
if (fnIt != factoryMap.end())
return fnIt->second();
else
throw "Bad animal type";
}
};
坦率地說,我不知道我在這裏的任何改進:更相當多的我還有我的字符串映射,沿可讀性較差的代碼行...
在第一次執行第二次執行時是否有任何優點,並且有什麼方法可以擺脫該映射嗎?
我不太確定你想達到什麼目的?是否有某種你想要解決的現實生活問題? –
你可以添加'靜態Offspring * Animal :: createOffspring()= 0;'?這將使這個_REALLY_變得容易。否則,你將不得不用一個枚舉來替換你的字符串。 –
@MooingDuck我認爲你的意思是'virtual'而不是static'在你的評論中。 –