I think it is quite OK already, but from a design-pattern perspective, it would be interesting to hear if I have done it right.  I'm also interested to know whether the implementation is OK from a best-practice C++ point of view.I made a helper class in order to easily position objects in cocos2d-x. The client can use the class like this:restartButton->setPosition(                           Positioner()                           .withSize(restartButton->getContentSize())                           .withAlignment(HorizontalAlign::LEFT)                           .withAlignment(VerticalAlign::TOP)                           .withMargin(Position::LEFT, 1)                           .withContainer(ccp(0.0,0.0), contentSize)                           .build()                           );Here is the helper class:class VerticalAlign{     public:    enum ALIGNMENT    {        TOP,        CENTER,        BOTTOM    };};class HorizontalAlign{        public:    enum ALIGNMENT    {        LEFT,        CENTER,        RIGHT    };    static HorizontalAlign::ALIGNMENT     from(VerticalAlign::ALIGNMENT alignment)    {        switch (alignment)        {            case VerticalAlign::TOP:                return HorizontalAlign::RIGHT;                break;            case VerticalAlign::BOTTOM:                return HorizontalAlign::LEFT;                break;            case VerticalAlign::CENTER:                return HorizontalAlign::CENTER;                break;            default:                std::cerr << unexpected/unsupported alignment!\n;                throw new std::exception();        }    }};class Position{public:    enum POSITION    {        LEFT,        TOP,        RIGHT,        BOTTOM,        NR_POSITIONS    };};// origo for positions are at center,center (i.e. pos = 5,5 and size = 10,10 gives a top,left,right,bottom=5,5,15,15)class Positioner{public:    Positioner()    :    mHorizontalAlignemnt(HorizontalAlign::CENTER),    mVerticalAlignemnt(VerticalAlign::CENTER),    mContainerSize(cocos2d::CCSize(0.0,0.0)),    mContainerOrigo(ccp(0.0, 0.0))    {        mMargins.resize(Position::NR_POSITIONS);    }    virtual    ~Positioner()    {    }    Positioner &    withContainer(cocos2d::CCPoint containerOrigo, cocos2d::CCSize containerSize)    {        mContainerSize = containerSize;        mContainerOrigo = containerOrigo;        return *this;    }    Positioner &    withSize(cocos2d::CCSize size)    {        mSize = size;        return *this;    }    Positioner &    withAlignment(HorizontalAlign::ALIGNMENT align)    {        mHorizontalAlignemnt = align;        return *this;    }    Positioner &    withAlignment(VerticalAlign::ALIGNMENT align)    {        mVerticalAlignemnt = align;        return *this;    }    Positioner &    withMargin(Position::POSITION marginAt, double margin)    {        mMargins[marginAt] = margin;        return *this;    }    // returns origo of a rectangle with given size and vertically and horizontally aligned within a given container such that it meets the given margins    // however, alignment takes precedence over margins (i.e. if centered then will be positioned centered even if it does not meet the margins given)    CCPoint build()    {        return ccp(xOrigo(), yOrigo());    }private:    double xOrigo(HorizontalAlign::ALIGNMENT align, double marginLeft, double marginRight, double size, double containerOrigo, double containerSize)    {        switch (align)        {            case HorizontalAlign::LEFT:                return containerOrigo + size / 2.0 + marginLeft;                break;            case HorizontalAlign::RIGHT:                return containerOrigo - size / 2.0 - marginRight + containerSize;                break;            case HorizontalAlign::CENTER:                return containerOrigo + containerSize / 2.0;                break;            default:                std::cerr << unexpected/unsupported alignment!\n;                throw new std::exception();        }    }    double xOrigo()    {        return xOrigo(mHorizontalAlignemnt, mMargins[Position::LEFT], mMargins[Position::RIGHT], mSize.width, mContainerOrigo.x, mContainerSize.width);    }    double yOrigo()    {        return xOrigo(HorizontalAlign::from(mVerticalAlignemnt), mMargins[Position::TOP], mMargins[Position::BOTTOM], mSize.height, mContainerOrigo.y, mContainerSize.height);    }    HorizontalAlign::ALIGNMENT mHorizontalAlignemnt;    VerticalAlign::ALIGNMENT mVerticalAlignemnt;    cocos2d::CCSize mContainerSize;    cocos2d::CCPoint mContainerOrigo;    cocos2d::CCSize mSize;    std::vector<double> mMargins;};
Helper class for easily positioning objects in cocos2d-x
c++;design patterns
Let me offer a different point of view.Using a builder, in itself, is fine.Lokis alternative works nicely but if youve got more complex objects it doesnt scale any more. A builder can then be used as an alternative to keep the actual object (not the builder, the built object) immutable.To make it clear: in this case Id probably go with Lokis approach and Id use this approach as much as possible but sometimes a builder yields clearer code.But when you use a builder, make sure that you dont fall into the trap of constructing an unfinished object: that is, the build method should make sure that the constructed object is valid and complete, and should raise an exception if thats not the case. That way, youve made sure via the type system that the resulting object will be in a valid state.Furthermore, having a build method is Java cruft. In C++, you can just define an implicit conversion to the type you want to build. Although there are normally good reasons against implicit conversions, they dont apply in this particular case the conversion is safe (if you make it safe, see above) and should never lead to confusion.With that, Id replace build by the following:operator CCPoint() const{    verify_object_is_valid();    return ccp(xOrigo(), yOrigo());}And the usage is shortened a bit:restartButton->setPosition(    Positioner().withSize(restartButton->getContentSize())                .withAlignment(HorizontalAlign::LEFT)                .withAlignment(VerticalAlign::TOP)                .withMargin(Position::LEFT, 1)                .withContainer(ccp(0.0,0.0), contentSize));(Reformatting also helps.)But note that this is still longer, and not actually clearer, than Lokis alternative code without a builder.