Ovviamente ci sono piu modi di realizzare la cosa.

Se lo scopo è entrare nella filosofia della programmazione ad oggetti, inizierei a scommporre il problema in sottoproblemi e a pensare alle classi con cui implementare i vari moduli. Ad esempio, io userei una classe che rappresenta un'operazione; tale classe contiene gli operandi ed è in grado di eseguire l'operazione tra gli operandi.
Un'altra classe invece puo occupasrsi di fare il parsing dell'input dell'utente per ricavarne un oggetto che rappresenta un'operazione.

La Calcolatrice userebbe il Parser per interpretare l'input dell'utente, ovvero ricavare dall'input un oggetto oprazione, dopodichè può invocare un opportuno metodo sull'oggetto operazione per eseguire effettivamente l'operazione che rappresenta.

Questo approccio è molto aderente alla filosofia della progrmmazione ad oggetti, la calcolatrice non ha bisogno di preoccuparsi di come implementare le operazioni: saranno le apposite classi a fare questo; analogamente la calcolatrice non deve preoccuparsi di come effettuare il parsing: se domani decidi che i dati devono essere immessi in modo diverso è sufficiente implementare diversamenete solo la classe Parser; se vuoi aggiungere altre operazioni devi solo definire le relative classi.

Qui di seguito ti riporto in forma stringata le classi che io userei:

Codice PHP:

//E l'interfaccia che deve essere implemetate dalle classi che rappresentano un'operazione

interface Operazione{

    public 
double calcola();

}


//E una classe che rappresenta un'operazione unaria
//è astratta perche il metodo calcola non è implementato
abstract classe OperazioneUnaria implements Operazione{

    protected 
double primoOperando;

    public 
OperazioneUnaria(double operando){
        
primoOperando operando;
    }

    public abstract 
double calacla();

}

//Questa classe rappresenta un'operazione binaria aggiungendo 
//un secondo operando; anche questa è astratta
abstract classe OperazioneBinaria extends OperazioneUnaria{

    protected 
double secondoOperando;

    public 
OperazioneUnaria(double operando1double operando2){
        
super(operando1);
        
secondoOperandoOperando operando;
    }

    public abstract 
double calacla();

}


//Poi fai le varie implementazioni, in base alle diverse operazioni;


class RadiceQuadrata extends OperazioneUnaria{

    public 
double calcola(){
        return 
Math.sqrt(primoOperando);
    }
}

class 
Moltiplicazione extends OperazioneBinaria{

    public 
double calcola(){
        return 
primoOperando secondoOperando;
    }


e cosi per le altre operazioni che vuoi implementare

Subito dopo potresti pensare ad una classe Parser che riceve una stringa e capisce che operazione bisonga fare. Tale classe può offrire ad esempio un metodo pubblico parse(String s) che restituisce un oggetto di una classe che implementa Operazione.

Codice PHP:
class Parser{
   
   public static 
Operazione parse(String s){
       
//Supponiamo che la stringa s sia 4 * 2
       //Allora bisogna fare una moltiplicazione:
       
return new Moltiplicazione(42);
       
//Supponiamo che la stringa s sia 4 / 2
       //Allora bisogna fare una divisione:
       
return new Divisione(42);
       
//eccetera eccetera...
    
}

Ora, avendo queste classi a disposizione, una Calcolatrice deve semplicemente eseguire un ciclo continuo in cui:

1 - prende una stringa s di input dall'utente;
2 - invoca il metodo Parser.parse(s) della classe Parser, ottenendo un oggetto op che è un'Operazione;
3 - invocare su op il metodo calcola per avere i risultato e stamparlo.

Codice PHP:

class Calcolatrice{

    private 
void execute(){
       
String s null;       
       while(
true){
            
System.out.println("Immetti l'operazione da eseguire");
            
String s //....s contiene l'iput dell'utente
            
Operazione op Parser.parse(s);
            
float rislutato op.calcola();
            
System.out.println("il risultato è " risultato);
       }
    }

Nota: la calcolatrice non sa neanche se l'operazione che esegue è unaria o binaria, ma poichè ogni classe che rappresenta un'operazione implementa l'iterfaccia Operazione, la Calcolatrice sa che basta invocare il metodo calcola() per averne il risulatato.