I’m currently working on a class that calculates the difference between two objects. I’m trying to decide what the best design for this class would be. I see two options:
1) Single-use class instance. Takes the objects to diff in the constructor and calculates the diff for that.
public class MyObjDiffer { public MyObjDiffer(MyObj o1, MyObj o2) { // Calculate diff here and store results in member variables } public boolean areObjectsDifferent() { // ... } public Vector getOnlyInObj1() { // ... } public Vector getOnlyInObj2() { // ... } // ... }
2) Re-usable class instance. Constructor takes no arguments. Has a ‘calculateDiff()’ method that takes the objects to diff, and returns the results.
public class MyObjDiffer { public MyObjDiffer() { } public DiffResults getResults(MyObj o1, MyObj o2) { // calculate and return the results. Nothing is stored in this class's members. } } public class DiffResults { public boolean areObjectsDifferent() { // ... } public Vector getOnlyInObj1() { // ... } public Vector getOnlyInObj2() { // ... } }
The diffing will be fairly complex (details don’t matter for the question), so there will need to be a number of helper functions. If I take solution 1 then I can store the data in member variables and don’t have to pass everything around. It’s slightly more compact, as everything is handled within a single class.
However, conceptually, it seems weird that a ‘Differ’ would be specific to a certain set of results. Option 2 splits the results from the logic that actually calculates them.
EDIT: Option 2 also provides the ability to make the ‘MyObjDiffer’ class static. Thanks kitsune, I forgot to mention that.
I’m having trouble seeing any significant pro or con to either option. I figure this kind of thing (a class that just handles some one-shot calculation) has to come up fairly often, and maybe I’m missing something. So, I figured I’d pose the question to the cloud. Are there significant pros or cons to one or the other option here? Is one inherently better? Does it matter?
I am doing this in Java, so there might be some restrictions on the possibilities, but the overall question of design is probably language-agnostic.
Use Object-Oriented Programming
Use option 2, but do not make it static.
The Strategy Pattern
This way, an instance
MyObjDiffercan be passed to anyone that needs a Strategy for computing the difference between objects.If, down the road, you find that different rules are used for computation in different contexts, you can create a new strategy to suit. With your code as it stands, you’d extend MyObjDiffer and override its methods, which is certainly workable. A better approach would be to define an interface, and have MyObjDiffer as one implementation.
Any decent refactoring tool will be able to ‘extract an interface’ from MyObjDiffer and replace references to that type with the interface type at some later time if you want to delay the decision. Using ‘Option 2’ with instance methods, rather than class procedures, gives you that flexibility.
Configure an Instance
Even if you never need to write a new comparison method, you might find that specifying options to tailor the behavior of your basic method is useful. If you think about using the ‘diff’ command to compare text files, you’ll remember how many different options there are: whitespace- and case-sensitivity, output options, etc. The best analog to this in OO programming is to consider each diff process as an object, with options set as properties on that object.