I am looking for advice on the most elegant and secure way to decouple two C++ classes that maintain collections of pointers to each other's types.
I implemented it recently using a common base class for polymorphism and was told that it was an unsatisfactory solution. I am eager to learn other ways this can be achieved.
Thanks in advance...
I have added a simplified version of the class definitions below. I am aware that the SalesTeam
class is not decoupled from SalesPerson
here.
// Global Vectors
vector<Customer *> v_Customer;
vector<SalesPerson *> v_SalesPerson;
vector<SalesTeam *> v_SalesTeam;
class Person { // Base Class
};
class Customer: public Person {
private:
const Person *contact; // This is the SalesPerson that serves the Customer
public:
Customer(const int aBirthYear);
virtual ~Customer() {}
};
class SalesPerson: public Person {
private:
vector<Person *> v_Client; // These are the customers that the SalesPerson serves
public:
SalesPerson();
virtual ~SalesPerson(){};
};
class SalesTeam {
private:
vector<SalesPerson *> v_TeamMember; // These are the sales people in the SalesTeam
public:
SalesTeam();
};
can you use mediator pattern to handle this decouple issue? code example:
class Mediator
{
private:
//store your relationship in this class
}
class SalesPerson: public Person {
private:
Mediator mediator;
public:
SalesPerson();
virtual ~SalesPerson(){};
};
class SalesTeam {
private:
Mediator mediator;
public:
SalesTeam();
};
The unsatisfactory part about your first solution is that the Customer and SalesPerson classes contain references to each other, which gets really hairy to manage. I think the "best" solution largely depends on how you intend on customers and sales people interacting with each other. From my assumptions about sales people and customers, I'm assuming that customers don't actually require the sales person and vice versa, instead their relationship would probably be defined in a third class ... such as a transaction.
class Transaction
{
private:
Customer *customer;
SalesPerson *employee;
}
There's hundreds, if not thousands, of design patterns but there is no universal pattern for every situation. I recommend drawing your objects on paper and connecting their references with arrows; if you draw a bi-directional arrow ( such as your Customer and SalesPerson relationships ) then stop and re-evaluate. Once your diagram is complete, you can use the arrows to visualize your interfaces for each object to understand how everything fits together.
You can eliminate the person class by using forward declaration.
// Global Vectors
vector<Customer *> v_Customer;
vector<SalesPerson *> v_SalesPerson;
vector<SalesTeam *> v_SalesTeam;
class SalesPerson; //<-- forward declaration for contact
class Customer {
const SalesPerson *contact;
public:
Customer(const int aBirthYear);
virtual ~Customer() {}
};
class SalesPerson {
vector<Customer *> v_Client;
public:
SalesPerson();
virtual ~SalesPerson(){};
};
class SalesTeam {
vector<SalesPerson *> v_TeamMember;
public:
SalesTeam();
};