Dav*_*ria 42 language-agnostic oop design-patterns
我正在阅读"清洁代码",并且无法弄清楚如何将我的一些功能(通常是构造函数)保持为最多3个参数.
通常我的对象需要大量的信息才能工作 - 我是否应该创建一个小构造函数,然后使用mutator函数为它们提供所有信息?这似乎没有比使用一个大的构造函数更好.
举个例子,我有一个"MovablePatch"类.它允许用户在窗口中拖动方块.它需要几个参数,包括Radius,Color,Renderer,InitialPosition和Visibility.目前我从我的GUI收集所有这些,然后调用:
MovablePatch(int radius, Renderer* renderer, Color color, Position initial, bool visibility)
Run Code Online (Sandbox Code Playgroud)
这些只是我在这堂课中需要的一些东西.任何人都可以建议我如何打包这些信息传递给构造函数?我没有看到任何明显的"打破小班"在这里出现.
Ada*_*ruk 31
你可以有
MovablePatch(Renderer* renderer, CircleAppearance circleAppearance)
Run Code Online (Sandbox Code Playgroud)
CircleAppearance收集其他信息.
但是,干净的代码和其他关于优秀代码应该是什么样子的书籍,目标是80%的代码.您的代码似乎比典型的LoB(业务线)品种"更接近金属".因此,您可能会遇到某些编码理想不适用的地方.
最重要的部分是你正在考虑它并试图让事情变得干净整洁!:)
Mik*_*kis 29
不要把"你的建造者中不要超过3个参数"这样的格言视为面值.如果你有一点机会使一个对象不可变,那就去做吧; 如果它是不可变的意味着它将有一个包含50个参数的构造函数,那就这样吧; 去吧; 甚至不考虑它两次.
即使对象是可变的,仍然应该根据需要传递其构造函数,以便在构造时立即处于有效且有意义的状态.在我的书中,绝对不允许必须知道哪些是必须被调用的神奇的mutator方法(有时甚至以正确的顺序),然后才能调用任何其他方法,在段错误的惩罚下.
话虽如此,如果您真的想减少构造函数或任何函数的参数数量,只需将此方法传递给它可以调用的接口,以便从中获取所需的东西以便工作.
Don*_*ner 21
你传递的一些东西可以被抽象成一个更大的构造.例如visibility
,color
和radius
,可能是有意义的放入您定义的对象.然后,这个类的一个实例,称之为ColoredCircle
,可以传递给构造函数MovablePatch
.ColoredCircle并不关心它在哪里或者它正在使用什么渲染器,但是MovablePatch可以.
我的主要观点是,从OO的角度来看,radius
它不是一个整数,它是一个半径.您希望避免使用这些长构造函数列表,因为理解这些内容的上下文是令人畏惧的.如果它们收集到一个更大的类,有点喜欢你已经有Color
和Position
,您可以在通过更少的参数,使之更容易理解.
Sam*_*ler 12
该命名参数成语在这里很有用.在你的情况下,你可能有
class PatchBuilder
{
public:
PatchBuilder() { }
PatchBuilder& radius(int r) { _radius = r; return *this; }
PatchBuilder& renderer(Renderer* r) { _renderer = r; return *this; }
PatchBuilder& color(const Color& c) { _color = c; return *this; }
PatchBuilder& initial(const Position& p) { _position = p; return *this; }
PatchBuilder& visibility(bool v) { _visibility = v; return *this; }
private:
friend class MovablePatch;
int _radius;
Renderer* _renderer;
Color _color;
Position _position;
bool _visibility;
};
class MovablePatch
{
public:
MovablePatch( const PatchBuilder& b ) :
_radius( b._radius );
_renderer( b._renderer );
_color( b._color );
_position( b._position );
_visibility( b._visibility );
{
}
private:
int _radius;
Renderer* _renderer;
Color _color;
Position _position;
bool _visibility;
};
Run Code Online (Sandbox Code Playgroud)
然后你就这样使用它
int
main()
{
MovablePatch foo = PatchBuilder().
radius( 1.3 ).
renderer( asdf ).
color( asdf ).
position( asdf ).
visibility( true )
;
}
Run Code Online (Sandbox Code Playgroud)
过度简化,但我认为它得到了重点.如果需要某些参数,它们可以包含在PatchBuilder
构造函数中:
class PatchBuilder
{
public:
PatchBuilder(const Foo& required) : _foo(required) { }
...
};
Run Code Online (Sandbox Code Playgroud)
显然,如果需要所有参数,这种模式会退化为原始问题,在这种情况下,命名参数习惯用法不适用.关键是,这不是一个适合所有解决方案,并且正如亚当在下面的评论中描述的那样,还有额外的成本和一些开销.