namespace option_1 {
/*
* Friend class controls instantiation. Is only one with write access to members
*/
class Controller;
class Model
{
int _a, _b;
Model() = default;
public:
int a() const
{ return _a; }
int b() const
{ return _b; }
friend class Controller;
};
class Controller
{
Model _m;
public:
Controller()
: _m()
{
_m._a = 1;
_m._b = 2;
}
const Model* model() const
{ return &_m; }
};
int test()
{
Controller c;
const Model* m = c.model();
return m->a();
}
}
namespace option_2 {
/*
* Instantiation is not controlled but pointless so who cares?
* Controller returns const pointer to Model so Controller is still only
* one with write access to the only genuine Model object.
* To avoid accidental misuse, copy construction of Model is denied.
*/
class Controller;
class Model
{
int _a, _b;
public:
Model() = default;
Model(const Model&) = delete;
Model& operator=(const Model&) = delete;
void a(int a)
{ _a = a; }
void b(int b)
{ _b = b; }
int a() const
{ return _a; }
int b() const
{ return _b; }
};
class Controller
{
Model _m;
public:
Controller()
: _m()
{
_m.a(1);
_m.b(2);
}
const Model* model() const
{ return &_m; }
};
int test()
{
Controller c;
const Model* m = c.model();
return m->a();
}
}
namespace option_3 {
/*
* A weird little trick: Abuse private inheritance to hide the model in the
* inheritance hierarchy of the controller.
* I wouldn't consider this good design but it's a neat trick for corner
* cases.
*/
class Model
{
protected:
int _a, _b;
Model() = default;
~Model() = default;
public:
Model(const Model&) = delete;
Model& operator=(const Model&) = delete;
int a() const
{ return _a; }
int b() const
{ return _b; }
};
class Controller: private Model
{
public:
Controller()
{
_a = 1;
_b = 2;
}
const Model* model() const
{ return this; }
};
int test()
{
Controller c;
const Model* m = c.model();
return m->a();
}
}
namespace option_4 {
/*
* Cleaner version of option_3. Modifiers for Model are restricted to a
* subclass that only Controller can access.
*/
class Model
{
protected:
int _a, _b;
Model() = default;
~Model() = default;
public:
Model(const Model&) = delete;
Model& operator=(const Model&) = delete;
int a() const
{ return _a; }
int b() const
{ return _b; }
};
class Controller
{
class MutableModel: public Model
{
public:
void a(int a)
{ _a = a; }
void b(int b)
{ _b = b; }
};
MutableModel _m;
public:
Controller()
{
_m.a(1);
_m.b(2);
}
const Model* model() const
{ return &_m; }
};
int test()
{
Controller c;
const Model* m = c.model();
return m->a();
}
}
Comments