Question about the structure of the class. What to choose?

What are (if any) implied assumptions or limitations and design differences, such as:

A):

class SampleClass1 { IWorker workerA; IWorker workerB; void setWorkerA(IWorker w); void setWorkerB(IWorker w); WorkResult doWork(); } 

B) compared to this:

 class SampleClass2 { WorkResult doWork(IWorker workerA, IWorker workerB); } 

I know this depends on the specific project, but what if the above class is part of a small structure? The first class is able to maintain state and separate the steps more naturally, but the second class provides “real-time communication” with the external caller in a more natural way, since the worker is transferred every time doWork () is called.

Are there any recommended uses or general methods that determine the choice between the two above methods? Thanks.

+6
class-design
source share
8 answers

In option (A) you create a so-called functional object or functor, this is a well-documented design template.

The two main advantages are:

  • Workers can be installed in one place, and then an object used in another place.
  • An object can maintain state between calls

Also, if you use the dependency injection infrastructure (Spring, Guice, etc.), the functor can be automatically initialized and entered where it is needed.

Function objects are widely used in libraries, for example. C ++ standard library of templates

+5
source share

SampleClass1

  • I may need to maintain working state between doWork
  • I may need the opportunity to customize Workers. (doWork from 1 and 2, then from 2 and 3)
  • I want to support the workers, because it can be expected that they will work several times for the same workers.
  • I am not a utility class. The instance of me is very important.

SampleClass2

  • Give me two workers, and I will work with them.
  • I don’t care who they are, and I don’t want to support them.
  • This is someone else to keep in touch between the workers.
  • I can be a more useful class. Maybe I can just be static.
+6
source share

Another option, case A option, is as follows:

  class SampleClass3
 {
     SampleClass3 (IWorker workerA, IWorker workerB);
     WorkResult doWork ();
 }

Benefits:

  • It is more difficult to make the object defective, since you need to provide all the workers who are needed during construction (unlike case A).

  • You can save the state inside SampleClass3 and / or one of the workers. (This is not possible in case B.)

Disadvantages:

  • You must have all of your workers before you create SampleClass3, instead of providing them later. Of course, you can also provide setters so that you can change them later.
+2
source share

If several methods depend on IWorker a and IWorker b, I say example A.

If only doWork () uses both IWorker a and IWorker b, then example B.

Also, what is the real purpose of your SampleClass? doWork looks a bit like a useful mroe method than anything else.

+1
source share

A) - poor design, because it allows the defect of the object (one or both work classes may not be installed).

B) may be good. Make it static, but if you are not dependent on the internal state of SampleClass2

+1
source share

Another variant:

IWorker Class:

static WorkResult doWork (Iworker a, Iworker b);

0
source share

IMO's second approach looks better; it requires the caller to use less code to complete the task. The second approach is less error prone, the caller does not need to worry that the object cannot be fully initialized.

0
source share

How about defining a WorkDelegate (or, alternatively, an interface having a single doWork method without an argument) that simply returns a WorkResult and allows individual classes to decide how they implement it? Thus, you are not limited to premature decisions.

0
source share

All Articles