2011-10-21 11 views
6

Ho una classe davvero terribile con due metodi che avviano o interrompono alcuni servizi quando tali servizi sono disponibili. Qualcosa di simile a quanto segue (non sono se-elses, solo se):Un modello di progettazione per evitare più ifs

void startServices() { 
if (service1 == true) { 
    start1(); 
} 
if (service2 == true) { 
    start2(); 
} if (serviceN == true) { 
    startN(); 
} 
} 


void stopServices() { 
if (service1 == true) { 
    stop1(); 
} 
if (service2 == true) { 
    stop2(); 
} 
if (serviceN == true) { 
    stopN(); 
} 

} 

cosa mi consiglia qualsiasi scalpiccio di design per renderlo più bello?

Grazie!

+0

Non risponderò a questo perché le risposte esistenti sono buone, ma vorrei solo sottolineare che '== true' è un po 'ridondante in qualsiasi' if() '. –

risposta

4

Depends; la mia prima reazione è quella di memorizzare i servizi in un hash o array. Ogni servizio implementa un'interfaccia con i metodi start e stop. L'avvio o l'arresto di un servizio richiede solo una chiave o un indice di servizio.

È ancora un po 'fragile, forse, ma senza sapere di più non sono sicuro di come "domainify" ut così sembra più come quello che stai facendo.

4

È possibile utilizzare il modello di strategia.

L'idea è che si dovrebbe sapere quale strategia si intende utilizzare quando si crea un'istanza della classe (oppure è possibile modificarla in modo dinamico latrr). Pertanto, è possibile passare in tale strategia al momento dell'istanziazione (e facoltativamente sostituirlo in seguito).

public interface IStartupStrategy 
{ 
    void Start(); 
} 

public interface IStopStrategy 
{ 
    void Stop(); 
} 

public class MyClass 
{ 
    private readonly IEnumerable<IStartupStrategy> startupStrategies; 
    private readonly IEnumerable<IStopStrategy> stopStrategies; 

    public MyClass(IEnumerable<IStartupStrategy> startup, IEnumerable<IStopStrategy> stop) 
    { 
     this.startupStrategies = startup; 
     this.stopStrategies = stop; 
    } 

    public void Start() 
    { 
     foreach(var strategy in this.startupStrategies) 
     { 
      strategy.Start(); 
     } 
    } 

    public void Stop() 
    { 
     foreach(var strategy in this.stopStrategies) 
     { 
      strategy.Stop(); 
     } 
    } 
} 
+0

Ciò mi dà l'impressione che il modello di strategia fosse applicato ciecamente a questo problema. Non penso che il nome abbia troppo senso; ci sono più strategie di start-up? Uno per ogni servizio? – Guven

+1

Infatti. Stavo tentando di dare una chiara rappresentazione del pattern, ma così facendo ho rotto ciò che * dovrebbe * essere stato un "IService" in più start e stop strategie. Idealmente useresti l'interfaccia "IService" che avrebbe i metodi start e stop. Quindi quel servizio può decidere se vuole implementare l'avvio o l'arresto. I servizi verranno inoltrati in base a quali servizi sono disponibili e la classe chiamante deciderà * quando * tali servizi dovrebbero essere avviati o arrestati. È ancora il modello di strategia, ma la strategia avrebbe più di un metodo. –

+0

Ho appena riletto ciò che ho scritto nel commento precedente. Se il modello strategico sta essenzialmente passando in qualche algoritmo da eseguire che la classe chiamante non fornisce ... l'inversione del controllo nel suo insieme potrebbe essere considerata un modello di strategia? Solo un pensiero. –

2

Utilizzare Oggetti, in cui si dispone di un elenco di Servizi che è possibile iterare spegnendoli con un metodo ereditato stop().

public interface Service { 
    void start(); 
    void stop(); 
} 

public class TestService implements Service { 
    @Override 
    void start() { 
    } 

    @Override 
    void stop() { 
    } 
} 

Ogni servizio può anche memorizzare il suo stato in modo tale da spegnerli solo se attivi.

0

Le istruzioni di commutazione sono meno confuse. Se usato insieme al codice enumerico diventa molto leggibile.

Problemi correlati