2013-02-24 63 views
0

我有一个用于创建类的工厂方法模式,我想在继续实际创建之前验证输入参数。我在这里处理两个类,A和B,他们每个都有自己的验证。鉴于我已经在我的创建模板函数中传递类类型(A或B),我想直接使用该类型来告诉我需要使用哪种验证。我正在考虑使用模板功能专业化或虚拟输入参数来做到这一点,每个都有自己的优点/缺点。请让我知道,如果他们中的任何一个看起来更合理,或者也有其他选择。谢谢!模板功能专业化与虚拟输入变量?

噢,我确实考虑将验证作为A或B的静态方法,但这看起来不太好,因为我正在处理遗留代码,并且移动这些东西并不太直截了当。尽管如此,为了完整性,我还在下面展示了这个选项。

模板功能专业化:

临:可以使用传递到FactoryCreateClass方法类型直接选择验证

缺点:不被利用模板方法,因为只有专业化

template <typename T> 
void FactoryCreateClass (int, double) 
(
    bool bSuccess = ValidateBlock<T>(int, double); 

    if (bSuccess) 
     T* = T::CreateInstance();   
) 

template <typename T> 
bool ValidateBlock (int double); // don't need an implementation here since 
            // all specialization require different validation 

template <> 
bool ValidateBlock<A> (int, double) 
{ 
    //do validation before creating A 
} 

template <> 
bool ValidateBlock<B> (int, double) 
{ 
    //do validation before creating B 
} 

哑变量:

优点:能够使用传入FactoryCreateClass方法直接式LY用于选择验证

缺点:未使用的虚拟变量

template <typename T> 
void FactoryCreateClass (int, double) 
(
    bool bSuccess = ValidateBlock(T /*dummy*/, int, double); 

    if (bSuccess) 
     T* = T::CreateInstance();   
) 

bool ValidateBlock (A/*dummy*/, int, double) 
{ 
    //do validation before creating A 
} 

bool ValidateBlock (B/*dummy*/, int, double) 
{ 
    //do validation before creating B 
} 

静态类方法:

临:能够使用传递到FactoryCreateClass方法类型直接用于选择验证

缺点:哈德在遗留代码中进行这种类型的更改

template <typename T> 
void FactoryCreateClass (int, double) 
(
    bool bSuccess = T::ValidateBlock(int, double); 

    if (bSuccess) 
     T* = T::CreateInstance();   
) 

static bool A::ValidateBlock (int, double) 
{ 
    //do validation before creating A 
} 

static bool B::ValidateBlock (int, double) 
{ 
    //do validation before creating B 
} 

回答

1

你已经忘记了第三种选择:使用特质。

template <typename> struct Trait; 

template <> 
struct Trait<A> { 
    static bool Validate(int, double); 
}; 

template <> 
struct Trait<B> { 
    static bool Validate(int, double); 
}; 

然后:

template <typename T> 
void FactoryCreateClass(int i, double d) { 
    bool const success = Trait<T>::Validate(i, d); 
    // ... 
} 

当然不过,真正的问题是,为什么不这样做在CreateInstance直接验证?

+0

我抽象这个事实了,但实际上A和B的继承相同的基类,他们实际上使用基类的实现来执行创建实例。所以在CreateInstance中使用它的缺点与静态类方法的缺点非常相似:在遗留代码中进行这种类型的更改并不那么简单。 说了这么多,看起来我们至少有3种方法可以做到这一点。 **任何偏好?**只是想听取别人的意见。 – lancery 2013-02-24 23:42:26

+0

@lancery:我通常更喜欢功能/方法专业化的特质实现。更通用的,作为一个特质可以模板化,而方法不能部分专业化。而且我更喜欢通过直接因为可扩展性而对类进行黑客攻击的特性实现(我实际上并不需要以这种方式触摸类)。 – 2013-02-25 08:10:49

1

这里最合适的设计是在CreateInstance方法中进行验证,因为任务(args验证和实例创建)是强耦合的,并且在一个地方将这些东西集中在一起更具可读性。

但是,可能是这种情况,您不能更改CreateInstance方法的代码。那么,我看到使用函数模板或虚拟变量之间没有显着差异。后者,但是,更明确一些,因此更具可读性。

顺便说一句,不再被引用的变量是真的不是一个大问题,您可以抑制它,看到 Disable single warning error,搜索UNREFERENCED_PARAMETER

+0

我抽象出了这个事实,但实际上A和B从相同的基类继承而来,实际上它们使用基类的实现来执行创建实例。所以在CreateInstance中使用它的缺点与静态类方法的缺点非常相似:在遗留代码中进行这种类型的更改并不那么简单。所以它看起来像你的首选是虚拟变量的使用,因为它更加明确和可读。感谢您的反馈意见! – lancery 2013-02-24 23:46:21