I solve the problem of finding a leader ( leader election ).
The task is purely algorithmic. There are 2 forms of task. I have an abstract class for representing data and an abstract class Solver. For each form of the task I extend these classes in accordance with the needs of this form of task. That is, solving the problem for the first form, I need to write like this in the client code:
MyData data = new MyDataForm1(); MySolver solver = new MySolverForm1(); This could be compiled like this:
public abstract class AbstractTask{ // some code } public class Task1{ MyData data = new MyDataForm1(); MySolver solver = new MySolverForm1(); //some code } public class Task2{ MyData data = new MyDataForm2(); MySolver solver = new MySolverForm2(); //some code } Then in the client code for the first form, for example, you can do this:
AbstractTask task = new Task1(); Is this a composition? But there is such a problem: It turns out that Task 2 classes have responsibilities. They store the data and solve the problem (yes, delegating it to MyData and MySolver instances, but still). And so it always turns out with composition. We include instances of several classes in one class as fields. The included classes had some responsibilities. So the inclusive class will have several responsibilities.
I understand here that this is a higher level of abstraction. For example, at the level of individual parts of the machine, you can consider the motor, radio and steering wheel as separate classes that perform some duties. But then we start to consider the car. It consists of these parts. But now we are considering a higher level of abstraction (we just have to drive), so we can say that the class Machine still performs only one task (driving).