0

I have a number of classes forming a class hierarchy with base classes and their inheritances. Each class is quite large by taking several responsibilities, although those responsibilities are not coupled. I put the different responsibilities together in a class because I can easily use them consistently(I cannot express it very clearly, please see the illustrating code). But this seems not a good design. How can I split the large class while keeping it easy to use? Thanks for your suggestion and comments! The below please find the illustrating code.

// Base class.
class Base
{
public:
    // For responsibility A
    virtual void A1();
    virtual void A2();
    ...

    // For responsibility B
    virtual void B1();
    virtual void B2();
    ...

    // More responsibilites.
    ...
};

// Derived class 1.
class Derived_1 : public Base
{...};

// More derived classes.
...

// A function use it.
void Fun()
{
    Base* p = new Derived_1;
    p->A1(); // Here A1 and B1 are binded in the class Base, thus it make sure
    p->B1(); // their uses are consistent. If they are separated, how to ensure it? 
}
user1899020
  • 13,167
  • 21
  • 79
  • 154

2 Answers2

2

By having more than one responsibility in a class, you're breaking the Single Responsibility Principle of design.

Generally, good designs follow the SOLID principles.

Break up your classes.

  1. Define an interface for each responsibility.
  2. Try not to use multiple inheritance - use composition instead.

I've added some sample code to illustrate the concept:

#include <iostream>

//Interface for A
class ResponsibilityA
{
    public:
    virtual ~ResponsibilityA(){};
        virtual void A1() = 0;
        virtual void A2() = 0;
};


//Interface for B
class ResponsibilityB
{
        public:
    virtual ~ResponsibilityB(){};
        virtual void B1() = 0;
        virtual void B2() = 0;
};

//Concrete classes for each interface
class ResponsibilityAExecutor : public ResponsibilityA
{
        public:
        virtual void A1(){ std::cout<<"A1 executed\n"; };
        virtual void A2(){ std::cout<<"A2 executed\n"; };
};

class ResponsibilityBExecutor : public ResponsibilityB
{
        public:
        virtual void B1(){ std::cout<<"B1 executed\n"; }
        virtual void B2(){ std::cout<<"B2 executed\n"; }
};

// Now we use the interface implementations in a class that needs
// to combine both responsibilities
class PlanExecutor
{
public:
        PlanExecutor( ResponsibilityA& a, ResponsibilityB& b ) : 
        a_(a),
        b_(b)
        {

        }
        void ExecutePlan()
        {
                std::cout<<"Executing first part of the plan:\n";
                a_.A1();
                b_.B1();
                std::cout<<"Executing second part of the plan\n";
                a_.A2();
                b_.B2();
        }
private:
        ResponsibilityA &a_;
        ResponsibilityB &b_;    
};

int main()
{
        ResponsibilityAExecutor a;
        ResponsibilityBExecutor b;
        PlanExecutor p(a,b);
        p.ExecutePlan();
        return 0;
}

Finally, I also need to emphasize the importance of naming.

Community
  • 1
  • 1
Carl
  • 43,122
  • 10
  • 80
  • 104
0

I would say if Responsibilities of A and B are totally different the create separate classes for both of them and let the child implement what they want this way some child want only A or only B or both and it keeps it manageable and maintainable

// Base class.
class Base
{
public:
    // For responsibility A
**Goes to class A**
    virtual void A1();
    virtual void A2();
    ...


**//Goes to class B**
    // For responsibility B
    virtual void B1();
    virtual void B2();
    ...

    // More responsibilites.
    ...
};

// Derived class 1.
class Derived_1 : public Base **//inherits from A**
{...}; 

class Derived_2:Public A,Public B
sumeet kumar
  • 2,628
  • 1
  • 16
  • 24