好的,所以你在系统的主类周围撒了很多方法。所以你做了正确的事情,并通过创建一个新类进行重构,并将移动方法执行到一个新类中。新类有一个单一的责任,所有的事情都是正确的:
class Feature
{
public:
Feature(){};
void doSomething();
void doSomething1();
void doSomething2();
};
所以现在你原来的类有一个对象类型的成员变量:
Feature _feature;
现在,如果你这样做很多次,你将有许多成员对象在你的主类。
现在,根据配置可能需要或不需要这些功能,因此在某种程度上,拥有所有这些可能需要或不需要的对象是昂贵的。
任何人都可以提出一种改进的方法?
编辑:根据建议使用空对象设计模式我想出了这个:
定义功能接口的抽象类:
class IFeature
{
public:
virtual void doSomething()=0;
virtual void doSomething1()=0;
virtual void doSomething2()=0;
virtual ~IFeature(){}
};
然后,我定义了两个实现接口的类,一个真正的实现和一个空对象:
class RealFeature:public IFeature
{
public:
RealFeature(){};
void doSomething(){std::cout<<"RealFeature doSomething()"<<std::endl;}
void doSomething1(){std::cout<<"RealFeature doSomething()"<<std::endl;}
void doSomething2(){std::cout<<"RealFeature doSomething()"<<std::endl;}
};
class NullFeature:public IFeature
{
public:
NullFeature(){};
void doSomething(){std::cout<<"NULL doSomething()"<<std::endl;};
void doSomething1(){std::cout<<"NULL doSomething1()"<<std::endl;};
void doSomething2(){std::cout<<"NULL doSomething2()"<<std::endl;};
};
然后我定义一个类,它将根据配置委托给真实对象或空对象:
class Feature:public IFeature
{
public:
Feature();
~Feature();
void doSomething();
void doSomething1();
void doSomething2();
private:
std::auto_ptr<IFeature> _feature;
};
执行情况:
Feature::Feature()
{
std::cout<<"Feature() CTOR"<<std::endl;
if(configuration::isEnabled() )
{
_feature = auto_ptr<IFeature>( new RealFeature() );
}
else
{
_feature = auto_ptr<IFeature>( new NullFeature() );
}
}
void Feature::doSomething()
{
_feature->doSomething();
}
//And so one for each of the implementation methods
然后我在我的主类中使用类(或任何需要的地方):
Feature _feature;
_feature.doSomething();
如果缺少一个功能,正确的做法是忽略这个事实,什么也不做,你可以使用Null Object pattern来摆脱你的检查:
class MainThing {
IFeature _feature;
void DoStuff() {
_feature.Method1();
_feature.Method2();
}
intece IFeature {
void Method1();
void Method2();
}
class SomeFeature { /* ... */ }
class NullFeature {
void Method1() { /* do nothing */ }
void Method2() { /* do nothing */ }
}
现在,在MainThing
中,如果不存在可选功能,则为其提供对NullFeature
的引用,而不是实际的null
引用。这样,MainThing
始终可以安全地假设_feature
不是null
。
一个 auto_ptr 本身不会给你买太多。但是有一个指向一个对象的指针,你只有在需要的时候才懒洋洋地加载它。像:
class Foo {
private:
Feature* _feature;
public:
Foo() : _feature(NULL) {}
Feature* getFeature() {
if (! _feature) {
_feature = new Feature();
}
return _feature;
}
};
现在,如果您需要有关内存管理的帮助,可以将Feature*
包装在智能指针中。但是关键不在内存管理中,而是延迟创建。这样做的好处是,您不必在启动过程中选择性地配置要创建的内容-只需按需付费即可。有时这就是您所需要的。
请注意,这个特定实现的一个缺点是,创建现在是在客户端第一次调用他们认为只是一个 getter 时进行的。如果创建对象很耗时,这可能会给您的客户端带来一些冲击,甚至是一个问题。它还使 getter 非 const,这也可能是一个问题。最后,它假设您拥有按需创建对象所需的一切,这可能是一个棘手的问题。
您的问题描述中有一个时刻,实际上会导致失败。如果您的功能不可用,则不应“just return”,应在调用之前检查功能的可用性!
尝试使用不同的方法设计主类。想想你的类的一些抽象描述符叫做FeatureMap
或类似的东西,它实际上存储了当前类的可用功能。
当您实现FeatureMap
时,一切都变得简单明了。只需确保(在调用之前),您的类具有此功能,然后才调用它。如果您遇到调用不受支持的功能的情况,请引发异常。
还要提一下,这个feature-lookup例程应该很快(我猜是这样),并且不会影响您的性能。
我不知道我是否直接回答你的问题(因为我对你的问题域没有任何想法,好吧,更好的解决方案总是特定于域),但希望这会让你以正确的方式思考。
关于您对 Null 对象模式的编辑:如果您已经有一个功能的公共接口 / 私有实现,那么创建一个 null 实现是没有意义的,因为公共接口可以是您的 null 实现,没有任何问题)。
具体来说,你可以有:
class FeatureImpl
{
public:
void doSomething() { /*real work here*/ }
};
class Feature
{
class FeatureImpl * _impl;
public:
Feature() : _impl(0) {}
void doSomething()
{
if(_impl)
_impl->doSomething();
// else case ... here's your null object implementation :)
}
// code to (optionally) initialize the implementation left out due to laziness
};
如果它是性能关键的,则此代码仅从 NULL 实现中受益(即使这样,if(_impl)
的成本在大多数情况下也可以忽略不计)。
本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(33条)