Calculator Object Oriented Design I am aiming to implement a calculator in an object-oriented way.

Here is the solution by using the strategy pattern.

Looking forward to some valuable comments.

package oopdesign.calculator;

public class AdditionStrategy implements CalculationStrategy {

    @Override
    public int calculate(int value1, int value2) {
        return value1 + value2;
    }
}


package oopdesign.calculator;

public interface CalculationStrategy {

    int calculate(int value1, int value2);
}


package oopdesign.calculator;

public class Calculator {

    public static Calculator instance = null;

    CalculationStrategy calculationStrategy;

    public void setCalculationStrategy(CalculationStrategy calculationStrategy) {
        this.calculationStrategy = calculationStrategy;
    }

    public static Calculator getInstance(){
        if(instance == null){
            instance = new Calculator();
        }
        return instance;
    }

    public int calculate(int value1, int value2) {
       return calculationStrategy.calculate(value1, value2);
    }
}


package oopdesign.calculator;

public class CalculatorMain {

    public static void main(String[] args) {

        Calculator c = Calculator.getInstance();

        c.setCalculationStrategy(new AdditionStrategy());
        System.out.println(c.calculate(5 ,2));

        c.setCalculationStrategy(new SubtractionStrategy());
        System.out.println(c.calculate(5 ,2));

        c.setCalculationStrategy(new MultiplicationStrategy());
        System.out.println(c.calculate(5 ,2));

        c.setCalculationStrategy(new DivideStrategy());
        System.out.println(c.calculate(5 ,2));
    }
}


package oopdesign.calculator;

public class DivideStrategy implements CalculationStrategy {

    @Override
    public int calculate(int value1, int value2) {
        return value1 / value2;
    }
}


package oopdesign.calculator;

public class MultiplicationStrategy implements  CalculationStrategy{

    @Override
    public int calculate(int value1, int value2) {
        return value1 * value2;
    }
}

package oopdesign.calculator;

public class SubtractionStrategy implements CalculationStrategy {

    @Override
    public int calculate(int value1, int value2) {
        return value1 - value2;
    }
}
Review:
From extensibility and in pro of having the possibility of including in future versions more operations, it is a good approach. The code is very simple, and it is easy to read so it is very good your design proposal.

The main purpose of applying design patterns is to simplify things, to reach the maximum level of abstraction and allow you to write meaningful code, not just repeat stuff

So, you did good.
However, there are some observations:
package oopdesign.calculator;

//Singleton is a good approach for this problem
public class Calculator {

    //By default any object is null
    //Do not put it as public, you have the getInstance method
    private static Calculator instance;

    //You are limiting the operations to handle
    CalculationStrategy calculationStrategy;

    //This is not a Singleton if you allow the default constructor (its public by default)
    private Calculator() {
    }

    public void setCalculationStrategy(CalculationStrategy calculationStrategy) {
        this.calculationStrategy = calculationStrategy;
    }

    public static Calculator getInstance() {
        if (instance == null)
            instance = new Calculator();
        return instance;
    }

    //You should think about handle the most general data type (this case double)
    public double calculate(double value1, double value2) {
       return calculationStrategy.calculate(value1, value2);
    }
}

package oopdesign.calculator;

public class CalculatorMain {

    public static void main(String[] args) {

        Calculator c = Calculator.getInstance();

        //There is a problem with it, you need to instanciate the strategies
        //each time you need to use it
        c.setCalculationStrategy(new AdditionStrategy());
        System.out.println(c.calculate(5,2));

        //It requires space, plus you are not being efficient by storing
        //there operations (calculation strategies)
        c.setCalculationStrategy(new SubtractionStrategy());
        System.out.println(c.calculate(5,2));

        c.setCalculationStrategy(new MultiplicationStrategy());
        System.out.println(c.calculate(5,2));

        c.setCalculationStrategy(new DivideStrategy());
        System.out.println(c.calculate(5,2));
    }
}

An alternative
import java.util.HashMap;
import java.util.Map;

public class Calculator {

    private static Calculator instance;

    //search in Constant time (approximately)
    private Map&lt;String, CalculationStrategy&gt; calculationStrategies;

    private Calculator() {
        calculationStrategies = new HashMap&lt;&gt;();
    }

    public void addCalculationStrategy(String name, CalculationStrategy strategy) {
        calculationStrategies.put(name, strategy);
    }

    public static Calculator getInstance() {
        if (instance == null)
            instance = new Calculator();
        return instance;
    }

    //double b... means that there may be 0 to n parameters
    //consider that there are unitary operators or functions in a calculator
    public double calculate(String name, double a, double... b) {
        return calculationStrategies.get(name).calculate(a, b);
    }
}

package oopdesign.calculator;

public class Main {

    public static void main(String[] args) {
        Calculator calculator = Calculator.getInstance();

        //Use a lambda instead
        calculator.addCalculationStrategy(&quot;+&quot;, (a, b) -&gt; a + b[0]);
        //[b] is taken as an array but is a variadic parameter
        calculator.addCalculationStrategy(&quot;-&quot;, (a, b) -&gt; a - b[0]);
        calculator.addCalculationStrategy(&quot;*&quot;, (a, b) -&gt; a * b[0]);
        calculator.addCalculationStrategy(&quot;/&quot;, (a, b) -&gt; a / b[0]);
        calculator.addCalculationStrategy(&quot;Abs&quot;, (a, b) -&gt; Math.abs(a));
        calculator.addCalculationStrategy(&quot;Cos&quot;, (a, b) -&gt; Math.cos(a));
        calculator.addCalculationStrategy(&quot;Sin&quot;, (a, b) -&gt; Math.sin(a));

        System.out.println(calculator.calculate(&quot;+&quot;, 1, 3));
        System.out.println(calculator.calculate(&quot;-&quot;, 1, 3));
        System.out.println(calculator.calculate(&quot;*&quot;, 1, 3));
        System.out.println(calculator.calculate(&quot;/&quot;, 1, 3));
        System.out.println(calculator.calculate(&quot;Abs&quot;, -66));
        System.out.println(calculator.calculate(&quot;Cos&quot;, 75));
        System.out.println(calculator.calculate(&quot;Sin&quot;, 28));
        System.out.println(calculator.calculate(&quot;+&quot;, 666, 777));
    }
}

About double b... read this post about Variadic function parameters, as I said, it is a way to have multiple parameters, From 0 To N parameters
Thanks for reading this answer.