homer512 icon

Friends with alternatives

homer512 | PRO | 11/10/15 03:33:30 PM UTC | 0 ⭐ | 767 👁️ | Never ⏰ | []
C++ |

3.2 KB

|

None

|

0 👍

/

0 👎

 
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