C++ 在这种情况下,谁应该构造对象?
我有以下课程:C++ 在这种情况下,谁应该构造对象?,c++,oop,C++,Oop,我有以下课程: class PluginLoader { public: PluginLoader(Logger&, PluginFactory&, ConflictResolver&); //Functions. private: //Members and functions }; Logger、PluginFactory和conflictcolver类都是将在应用程序中实现的接口类。我在主程序的顶层创建了一个PluginLoader对象。可
class PluginLoader
{
public:
PluginLoader(Logger&, PluginFactory&, ConflictResolver&);
//Functions.
private:
//Members and functions
};
Logger
、PluginFactory
和conflictcolver
类都是将在应用程序中实现的接口类。我在主程序的顶层创建了一个PluginLoader
对象。可以在该级别了解记录器。但是,PluginFactory
和ConflictResolver
仅在PluginLoader
类内部使用。所以在顶层创建他们的对象看起来很难看。我该怎么办?如果需要,我可以更改构造函数,尽管我希望保持原样。欢迎提出任何意见。谢谢。我会让PluginLoader类有指向这些类的指针。我会向前声明类,我不会在任何地方定义类,而是在实现文件中定义,这样其他人就看不见了。这是更好的封装,再加上这样做也减少了编译时间
我不会使用原始指针,但auto_ptr、scoped_ptr或unique_ptr应该可以工作
如果您在构造函数中创建这些对象,或者甚至在以后首次使用(惰性构造)时创建这些对象,那么您不需要向构造函数传递任何内容,您可以删除这些参数
编辑:
从其他评论来看,我可能误解了你的问题。如果您想拥有可自定义的对象,这些对象实现了一个接口,但可以是下面的任何对象,那么您必须在顶层创建它们,并像现在这样传入接口引用/指针
我认为可以使用模板将类类型“传递”到对象中,以便它可以为自己创建这些类。但是,使用模板会使类类型在编译时固定下来,这可能不是您想要的。我的印象是,您将在构造函数中公开内部内容以进行可能的自定义,但不是典型情况。如果这是正确的,那么一个想法是使这些参数成为可选的,并在没有提供的情况下在内部创建它们 从您的问题和评论来看,您似乎被两个看似冲突的设计原则所迷惑
- 你应该尽可能多地封装
- 您不应该在实现中硬连接所需对象的创建
在您的情况下,通过坚持第二个原则,您做得很好(至少从可见的界面上)。这是依赖注入的一个很好的例子。将PluginLoader从创建PluginFactory和ConflictResolver的责任中解放出来是件好事
现在,你认为你违反了第一条原则,这在某种程度上是正确的。因此,回头更仔细地重新审视您的设计问题
PluginLoader到底需要什么?它只需要引用somePluginFactory和ConflictResolver对象。但它不需要自己创造它们。如何解决这个问题
我可以想到两种方法:
- 具有另一个抽象级别,如在中所做的。在这里
建筑群(或在您的案例中明显复杂的建筑群)和
布线过程将移动到生成器对象。主程序不是
为如何做到这一点而烦恼。它只会触发建筑
过程
- 另一个工厂可以创建辅助对象,如
PluginFactory和ConflictResolver,只让PluginLoader知道
关于这个新工厂的界面。主程序可以创建
该工厂的一个具体实例,并传递给PluginBuilder
通过使用上述任一方法,您可以消除与原则2的冲突
祝你一切顺利
…类是将在应用程序中实现的所有接口类
…PluginFactory
和conflictcolver
仅在
PluginLoader
class
这基本上意味着,即使它们仅在内部使用,您也必须公开PluginFactory
和ConflictResolver
的存在,因为您需要客户端实现它们,然后以某种方式(在本例中通过构造函数)将自定义实现传递给PluginLoader
但是,通过用指针替换引用(最好是智能类型的、唯一的\u ptr将只是作业的工具),可以避免在顶层声明命名对象(在main
中为静态或自动):
其中CustomLogger
,CustomPluginFactory
和customconflictcolver
是Logger
的实现,PluginFactory
和ConflictResolver
。我认为解决方案是使用一种机制:因此,您可以通过更改一个字符串(可能从配置文件加载)来选择具体的PluginFactory
和ConflictResolver
我开发了一个C++中的依赖注入库。在应用程序中,您可以使用以下代码声明您的PluginLoader类:
REGISTERED_CLASS( PluginLoader, void, void )
{
...
private:
Plug< Logger > logger;
Plug< PluginFactory > pluginFactory;
Plug< ConflictResolver > conflictResolver;
};
catalog.Create( "loader", "PluginLoader" );
catalog.Create( "logger", "MyConcreteLogger" );
catalog.Create( "factory", "MyConcretePluginFactory" );
catalog.Create( "resolver", "MyConcreteResolver" );
wallaroo_within( catalog )
{
use( "logger" ).as( "logger" ).of( "loader" );
use( "factory" ).as( "pluginFactory" ).of( "loader" );
use( "resolver" ).as( "conflictResolver" ).of( "loader" );
}
我们为一个应用程序使用了类似的设计,该应用程序使用我们创建的dll。记录器在主应用程序中已知,并在dll中使用。但是,有些对象仅在dll内部使用。我仍然不清楚,如果它们只在内部使用,为什么它们甚至是插件加载程序接口的一部分。其他对象的任何部分是否在外部依赖于这些接口
我想说的是,为什么不为这两个参数使用工厂,PluginFactory,conflictcolver,而根本不将它们作为参数传递
e、 g。
插件加载程序(记录器和)
然后在您的实现中
PluginLoader(Logger& logger){
Factory::PluginFactory::GetInstance().useInstance;// example
Factory::ConflicResolver::GetInstance().useInstance;// exmaple
}
或者你可以详细说明一下?我不知道你在问什么,你在做什么。如果您不喜欢依赖注入(看起来这就是您在这里要做的——但是
<catalog>
<!-- build the objects of your app -->
<object>
<name>loader</name>
<class>PluginLoader</class>
</object>
<object>
<name>logger</name>
<class>MyConcreteLogger</class>
</object>
<object>
<name>factory</name>
<class>MyConcretePluginFactory</class>
</object>
<object>
<name>resolver</name>
<class>MyConcreteResolver</class>
</object>
<!-- wiring of the objects: -->
<relation>
<source>loader</source>
<dest>logger</dest>
<role>logger</role>
</relation>
<relation>
<source>loader</source>
<dest>factory</dest>
<role>pluginFactory</role>
</relation>
<relation>
<source>loader</source>
<dest>resolver</dest>
<role>conflictResolver</role>
</relation>
</catalog>
catalog.Create( "loader", "PluginLoader" );
catalog.Create( "logger", "MyConcreteLogger" );
catalog.Create( "factory", "MyConcretePluginFactory" );
catalog.Create( "resolver", "MyConcreteResolver" );
wallaroo_within( catalog )
{
use( "logger" ).as( "logger" ).of( "loader" );
use( "factory" ).as( "pluginFactory" ).of( "loader" );
use( "resolver" ).as( "conflictResolver" ).of( "loader" );
}
PluginLoader(Logger& logger){
Factory::PluginFactory::GetInstance().useInstance;// example
Factory::ConflicResolver::GetInstance().useInstance;// exmaple
}