3

My question is regarding the polymorphic Open-Closed Principle.

Say I have the following client:

public class Client {

    private Server server;

    public Client(Server server) {
        this.server = server;
    }

    public void purchase() {
        server.processPurchase(new Purchase());
    }
}

This is the abstraction for the server:

public interface Server {

    void processPurchase(Purchase purchase);
}

And the implementation for the server:

public class ServerImpl implements Server {

    @Override
    public void processPurchase(Purchase purchase) {
        System.out.println("Processing purchase" + purchase);
        processPayment(purchase);
    }

    private void processPayment(Purchase purchase) {
        System.out.println("Processing payment" + purchase);
    }
}

This minimalist use case is about performing a purchase.

Now say one wants to perform another action when I process the purchase e.g:

  • add purchase information to a database to be later used for machine learning suggestions
  • mail a confirmation email to the user
  • etc.

What would be the best way to achieve the change whilst still respecting the OCP ?

My first idea is to write a second implementation and swap it from the first one as follows:

public class ServerImpl2 implements Server {

    @Override
    public void processPurchase(Purchase purchase) {
        System.out.println("Processing purchase" + purchase);
        processPayment(purchase);
        sendConfirmationEmail(purchase);
    }

    private void processPayment(Purchase purchase) {
        System.out.println("Processing payment" + purchase);
    }

    private void sendConfirmationEmail(Purchase purchase) {
        System.out.println("Sending confirmation email");
    }
}

Is there another way ? Any input or suggestions welcome.

5

Polymorphic Open-closed principle states that you should override methods deriving from interfaces and not implementation.

By adding private method calls inside your implementation, you are not violating this in the slightest. This is only stating that should you ever derive from ServerImpl, you would only ever really need to override processPurchase method and not, say, sendConfirmationEmail for instance as this is an implementation-specific method.

It is absolutely fine to have private methods to help realize the public callable method processPurchase.

  • Thanks a lot for your reply! Two questions: What do you mean by: you should override methods deriving from interfaces and not implementation? Can you rephrase please? Secondly, can you confirm whether or not the second implementation (ServerImpl2 ) is needed or whether I can go ahead and modify the first implementation (ServerImpl )? – balteo Oct 3 '18 at 9:21
  • By deriving you mean extending as in inheritance? – balteo Oct 3 '18 at 9:26
  • 1
    First question: I mean OCP refers to not overriding behavior of methods which are part of the implementation (private methods) and not the public method itself. Second question: You should modify the implementation of ServerImpl unless you think you might need both of course. Third question: Yes, by "deriving" I mean extending here. – Neil Oct 3 '18 at 9:37
0

The open closed principle can be realised through the usage of interfaces. Using interfaces let’s you have great control on extending your classes, whilst also keeping you from modifying abilities from parents, etc.

I’m on mobile at the moment but below is an example.

Let’s say you have the following:

interface IEat
{
     void Eat(Food food);
}

abstract class Animal {} : IEat
{
    abstract void Eat() { ... }
}

Now we want to create a predator subtype which would extend functionality of animal, but importantly not modify the behaviour...

We can achieve this through using another interface (notably NOT through overwriting Animals functions).

interface Predator
{
    void HuntForFood()
}

class Predator : IEat, IPredator
{
    void Eat(Food food)
     {
          this.HuntForFood();
          // Carry on eating.
     }

     void HuntForFood()
     {
           ...
     }
}

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.