4

I have a complex class and I want to simplify it by implementing a facade class (assume I have no control on complex class). My problem is that complex class has many methods and I will just simplify some of them and rest of the will stay as they are. What I mean by "simplify" is explained below.

I want to find a way that if a method is implemented with facade then call it, if not then call the method in complex class. The reason I want this is to write less code :) [less is more]

Example:

Facade facade = // initialize
facade.simplified(); // defined in Facade class so call it

// not defined in Facade but exists in the complex class
// so call the one in the complex class
facade.alreadySimple(); 

The options that comes to mind mind are:

Option 1: Write a class holding a variable of complex class and implement complex ones then implement simple ones with direct delegation:

class Facade {
    private PowerfulButComplexClass realWorker = // initialize
    public void simplified() {
         // do stuff
    }
    public void alreadySimple() {
         realWorker.alreadySimple();
    }
    // more stuff
}

But with this approach I will need to implement all the simple methods with just a single delegation statement. So I need to write more code (it is simple though)

Option 2: Extend the complex class and implement simplified methods but then both simple and complex versions of these methods will be visible.

In python I can achieve similar behaviour like this:

class PowerfulButComplexClass(object):
    def alreadySimple(self):
        # really simple

    # some very complex methods


class Facade(object):
    def __init__(self):
        self.realworker = PowerfulButComplexClass()
    def simplified(self):
        # simplified version of complex methods in PowerfulButComplexClass

    def __getattribute__(self, key):
    """For rest of the PowerfulButComplexClass' methods use them as they are
    because they are simple enough.
    """
        try:
            # return simplified version if we did
            attr = object.__getattribute__(self, key)
        except AttributeError:
            # return PowerfulButComplexClass' version because it is already simple
            attr = object.__getattribute__(self.data, key)
        return attr


obj = Facace()
obj.simplified() # call the one we have defined
obj.alreadySimple( # call the one defined in PowerfulButComplexClass

So what is the Java way to achieve this?

Edit: What I mean by "simplify": A complex method can be either a method with too many arguments

void complex method(arg1, arg2, ..., argn) // n is sufficiently large

or a set of related methods that will almost always called together to achieve a single task

outArg1 = someMethod(arg1, arg2);
outArg2 = someOtherMethod(outArg1, arg3);
actualResult = someAnotherMethod(outArg2);

so we want to have something like this:

String simplified(arg1, arg2, arg3) {
    outArg1 = someMethod(arg1, arg2);
    outArg2 = someOtherMethod(outArg1, arg3);
    return someAnotherMethod(outArg2);
}
MERose
  • 4,048
  • 7
  • 53
  • 79
reader_1000
  • 2,473
  • 17
  • 15
  • 1
    What do you mean by simplify? Are your simpler methods faster specialisations, or just easier to read or something else? If its a specialisation optimisation then option 2 makes sense, and your simple method should test if the arguments allow the simple case and call the default complex superclass otherwise. Your Java IDE can write all your stubs for you. – Julian May 08 '12 at 20:23
  • I edited question to clarify what I mean by simplification. – reader_1000 May 09 '12 at 08:47
  • OK, so its not the class you want to simplify, its the program you plan to write using it. That makes more sense. I'm leaning more towards your encapsulation approach then. It means you will only implement the API you need for your program and you know when readingg your facade that none of the "extra" complexity of the root class is being used anywhere. This will simplify your unit tests. – Julian May 09 '12 at 09:10
  • I want to simplify a library class. That's why I called it "facade". Thanks for comments. – reader_1000 May 09 '12 at 19:59

4 Answers4

3

It's called Inheritence. Consider the following code:

class Complex {
    public function complex() { /* Complex Function */ }
    public function simple() { /* Already simple function */ }
}

class SimplifiedComplex extends Complex {
    public function complex() { /* Simplify Here */ }
}

The simple() method will work on a SimplifiedComplex object.

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • 1
    this way you could still access the `Complex.complex()` method, by explicitly casting to it: `((Complex) simplifiedComplexInstance).complex()`. – yair May 08 '12 at 20:26
  • 2
    @yair actually not. DownCasting still invokes the overriding method. However, from within the class you can call `super.complex()` and possibly add an explicit public method to do that. See more here: http://stackoverflow.com/questions/1032847/can-java-call-parent-overridden-method-in-other-objects-but-not-subtype – Guillaume Polet May 08 '12 at 20:32
  • @GuillaumePolet you got it right. So that makes Truth's solution complete, as far as the question related. – yair May 09 '12 at 06:37
  • This is the option 2 I have mentioned in question, but in the case of a simplification like reducing number of args, then both simple and complex method will be visible and we will not be able to extend simplified class with another class (single inheritance). But still this is a good way to achive this. – reader_1000 May 09 '12 at 19:56
2

I think you've already called it. I would go with Option 1. It provides the most flexibility given the rigidity of java.

I prefer it because it favors composition over inheritance. Although this creates more code, I find designs like this generally are easier to modify in the long run.

Inheritance should only be used to model strict "is a" relationships where the subclass necessarily has all the properties and behaviors of the base class. If you're using inheritance for anything else your asking for trouble.

Finally, I don't buy into the idea of "Less Is More"(Insert incredibly concise, indecipherable perl example here). I buy into the principle of "Code should be as simple as it needs to be and no simpler".

nsfyn55
  • 14,875
  • 8
  • 50
  • 77
  • I think we can count things like "Don't repeat yourself" and reusability in the scope of "less is more". In my opinion, writing less code is a good idea as long as it is not conflicting with maintainability, readability, etc. – reader_1000 May 10 '12 at 06:15
1

Depending on your use case, you might want to create a facade in front of some of the functionality in complex class by delegating (Option 1), and instead of providing support for the rest of the functionality in complex class, you provide means to access complex class directly (getComplexClass).

This might make the design clearer. Consider, for example, a complex class handling most of the features of a bank system. Creating a class named "Account" that has access to the complex class but only uses the methods relevant for a bank account helps the design. For convenience, the Account class could have a method getBankSystemForAccount or something similar.

Buhb
  • 7,088
  • 3
  • 24
  • 38
1

This is ugly in Java, but you can write a function that takes the name of the method you want to call, and a parameter list, and use reflection to find the appropriate method to call. This will be conceptually similar to how you'd do it in Python, except much uglier.

Lie Ryan
  • 62,238
  • 13
  • 100
  • 144