Concepts

Interfaces are Wonderful Things (Part 2)

Following on from the previous blog, where we described one way interfaces can help with segregating different pars of our application, let’s look at another way they can be useful:

2) Interfaces also allow us to generalise behaviour of similar objects

Imagine now that you are Professor Snape, and you want to dock 10 points from Gryffindor. Let’s assume, for now, that Gryffindor is the only house in existence. This irks you. You don’t like this. 10 points from Gryffindor!

public class Points {
    private int housePoints;

    public void addPoints(int points) {
        this.housePoints += points;
    }
}

public class SnapesSchedule {
    public static void main (String[] args) {
        Points gryffindor = new Points();
        gryffindor.addPoints(-10);
    }
}

Of course, the real wizarding world is much more complicated and we actually have 4 houses, and in true Snape style, you’d like to balance the books by awarding 10 points to Slytherin too. It would be useful to be able to call the same addPoints method as above, but (irritatingly) each house has a slightly different method when it comes to calculating points internally (Slytherin, being the cheats that they are, slyly double their points first without anyone knowing). We could have the following:

public class Points {
    private int housePoints;
    private String house;

    public Points(String house) {
        this.house = house;
    }

    public void addPoints(int points, String house) {
        if (house.equals("Gryffindor")) {
             addPointsTheGryffindorWay(points);
        } else if (house.equals("Slytherin")) {
             addPointsTheSlytherinWay(points);
        } else if …
        //keep going for all houses...
    }

    private void addPointsTheGryffindorWay(int points) {
        this.housePoints += points;
    }

    private void addPointsTheSlytherinWay(int points) {
        this.housePoints += 2 * points;
    }
    //continue for all houses...
}

public class SnapesSchedule {
    public static void main (String[] args) {
        Points gryffindor = new Points("Gryffindor");
        Points slytherin = new Points("Slytherin");
        gryffindor.addPoints(-10);
        slytherin.addPoints(10);
    }
}

This can very quickly get confusing, though – having to go through a lengthy if statement just to see what is going on. Fear not! Interfaces to the rescue, yet again!

Since we are broadly doing the same thing in each case, (adding points), if we just had a Points interface with an addPoints method, we could just define the correct implementation of “Points” and it will automatically add the points in the correct way:

public interface Points {
    void addPoints(int points);
}

public class GryffindorPoints implements Points {
    private int housePoints;

    @Override
    public void addPoints(int points) {
        this.housePoints += points;
    }
}

public class SlytherinPoints implements Points {
    private int housePoints;

    @Override
    public void addPoints(int points) {
        this.housePoints += 2 * points;
    }
}
//continue for all houses...

public class SnapesSchedule {
    public static void main (String[] args) {
	Points gryffindorPoints = new GryffindorPoints();
	Points slytherinPoints = new SlytherinPoints();

        gryffindorPoints.addPoints(-10);
        slytherinPoints.addPoints(10);
    }
}

This makes our lives easier, as it’s easy to see exactly what’s going on here without digging through thousands of lines of code, and each class now has a single well-defined purpose – so when Slytherin get caught for their conniving ways we can make the change to that single class without worrying about impacting the rest. It also keeps our tests focused on that one purpose. Happy days!

<<<< Interfaces: Part 1          >>>> Interfaces: Part 3

 

Advertisements

3 thoughts on “Interfaces are Wonderful Things (Part 2)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s