Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Polymorphism: Anti-Pattern?

I'm reading O'Reilly's "Programming Android" book, and I'm trying to wrap my head around the "Overrides and Callbacks" section starting on page 99. They use this as an example of good code:

public class MyModel {
    public MyModel(TextView textBox) {
        textBox.addTextChangedListener(
            new TextWatcher() {
                public void afterTextChanged(Editable s) {
                    handleTextChange(s);
                }
                // ...
    }
    void handleTextChange(Editable s) {
        // do something with s, the changed text.
    }
}

And later call this an anti-pattern due to lack of extensibility encapsulation:

public class MyModel implements TextWatcher {
    public MyModel(TextView textBox) {
        textBox.addTextChangedListener(this);
    }

    public void afterTextChanged(Editable s) {
        handleTextChange(s);
    }

    // ...

    void handleTextChange(Editable s) {
        // do something with s, the changed text.
    }
}

I don't see the functional difference between the two, aside from the second being a lot more readable. Both take a TextView, and implement a handler function to override. Wouldn't the second be just as easy to extend with something like this?

public class AnotherModel extends MyModel {
    @Override
    void handleTextChange(Editable s) {
         // another implementation
    }
}
like image 581
joshwoodward Avatar asked Dec 05 '12 14:12

joshwoodward


2 Answers

an anti-pattern due to lack of extensibility

Extensibility-wise, they're similar in that both approaches let a subclass easily modify the existing TextChangeListener by overriding handleTextChange; but they're different in that only approach #2 also makes it easy for a subclass to add a new TextChangeListener without modifying the existing (inherited) one.

Even if the superclass uses approach #1, the subclass could still add a new TextChangeListener by using approach #2; but if we're talking about the pattern to use in general, then a consistent use of approach #2 will afford more extensibility than a consistent use of approach #1.

like image 102
ruakh Avatar answered Nov 15 '22 02:11

ruakh


I wouldn't like the 2nd form, since the class implements an interface as a trick, not because the class naturally is a subtype of the interface.

The 2nd form can be manageable for simple cases, so it's ok unless it gets too messy.

In Java 8, we can use the 1st form in a better syntax:

    textBox.addTextChangedListener(this#handleTextChange);  // method reference
like image 2
irreputable Avatar answered Nov 15 '22 02:11

irreputable