Domanda

Ho provato a seguire i principi dell'iniezione di dipendenza, ma dopo aver letto questo articolo, so che sto facendo qualcosa di sbagliato.

Ecco la mia situazione: la mia applicazione riceve diversi tipi di posta fisica. Tutta la posta in arrivo passa attraverso il mio oggetto MailFunnel .

Mentre è in esecuzione, MailFunnel riceve diversi tipi di messaggi dall'esterno: scatola, cartolina e rivista.

Ogni tipo di posta deve essere gestito in modo diverso. Ad esempio, se arriva una scatola, potrebbe essere necessario registrare il peso prima di consegnarlo. Di conseguenza, ho oggetti BoxHandler , PostcardHandler e MagazineHandler .

Ogni volta che arriva un nuovo messaggio nel mio MailFunnel , istanzio un nuovo corrispondente MailHandler .

Ad esempio:

class MailFunnel
{
  void NewMailArrived( Mail mail )
  {
    switch (mail.type)
    {
      case BOX:
        BoxHandler * bob = new BoxHandler(shreddingPolicy, maxWeightPolicy);
        bob->get_to_work();
        break;

      case POSTCARD:
        PostcardHandler * frank = new PostcardHandler(coolPicturePolicy);
        frank->get_to_work();
        break;

      case MAGAZINE:
        MagazineHandler * nancy = new MagazineHandler(censorPolicy);
        nancy->get_to_work();
        break;
    }
  }

  private:
    MaxWeightPolcy & maxWeightPolicy;
    ShreddingPolicy & shreddingPolicy;
    CoolPicturePolicy & coolPicturePolicy;
    CensorPolicy & censorPolicy;
}

Da un lato, questo è fantastico perché significa che se ricevo cinque diversi messaggi di posta, ho immediatamente cinque diversi MailHandlers che lavorano contemporaneamente per occuparmi degli affari. Tuttavia, ciò significa anche che I mescolando la creazione di oggetti con la logica dell'applicazione - un grande no-no quando si tratta di Dependency Injection.

Inoltre, ho tutti questi riferimenti di politica in giro nel mio oggetto MailFunnel di cui MailFunnel non ha davvero bisogno. L'unico motivo per cui MailFunnel ha questi oggetti è passarli ai costruttori MailHandler . Ancora una volta, questa è un'altra cosa che voglio evitare .

Tutti i consigli sono benvenuti. Grazie!

È stato utile?

Soluzione

A me sembra più una fabbrica. Spostare l'invocazione del metodo get_to_work () fuori dall'invocazione e restituire il gestore. Il modello funziona abbastanza bene per una fabbrica.

class MailHandlerFactory
{
  IMailHandler*  GetHandler( Mail mail )
  {
    switch (mail.type)
    {
      case BOX:
        return new BoxHandler(shreddingPolicy, maxWeightPolicy);
        break;

      case POSTCARD:
        return new PostcardHandler(coolPicturePolicy);
        break;

      case MAGAZINE:
        return new MagazineHandler(censorPolicy);
        break;
    }
  }

  private:
    MaxWeightPolcy & maxWeightPolicy;
    ShreddingPolicy & shreddingPolicy;
    CoolPicturePolicy & coolPicturePolicy;
    CensorPolicy & censorPolicy;
}

class MailFunnel
{
    MailHandlerFactory* handlerFactory;

    MailFunnel( MailHandlerFactory* factory ) {
        handlerFactory = factory;
    }

    void NewMailArrived( Mail mail ) {
        IMailHandler handler = handlerFactory.GetHandler(mail);
        handler.get_to_work();
    }
}

Altri suggerimenti

Quando vedi quell'istruzione switch, pensa al polimorfismo. Questo design può essere esteso solo con modifiche. Lo rifarei in modo tale da poter aggiungere un nuovo comportamento aggiungendo classi. Questo è il principio di apertura / chiusura.

Perché non puoi avere solo tre metodi che sono sovraccarichi che accettano i diversi tipi di posta e poi fanno la cosa appropriata? O fai gestire ogni tipo da solo.

In effetti, se hai qualcosa di simile al tipo, è probabile che tu debba effettivamente avere tipi diversi.

Fondamentalmente fai quanto segue:

1) Rendi astratta la classe Mail.

2) Crea tre sottoclassi di posta, casella, PostCard e rivista

3) Fornisci a ciascuna sottoclasse un metodo per gestire la posta o centralizzalo in una HandlerFactory separata

4) Quando viene passato alla canalizzazione della posta, è sufficiente che chiami il metodo handle mail o che HandlerFactory gli passi la posta e recuperi il gestore appropriato. Ancora una volta, piuttosto che avere dichiarazioni di commutazione scomode ovunque, usa la lingua, questo è il tipo e il metodo di sovraccarico.

Se la gestione della posta diventa complessa e si desidera eliminarla, alla fine è possibile creare una classe di gestore di posta ed estrarre tali criteri in tale.

Puoi anche prendere in considerazione l'uso di un metodo template, poiché l'unica vera differenza tra ognuno di questi sembra essere il gestore che istanza, forse potresti semplificarlo, in modo che il tipo di posta determini il gestore, il resto del codice è praticamente lo stesso.

Interessante che stai applicando l'iniezione di dipendenza a un progetto C ++; è stato fatto altrove, una rapida ricerca su Google trova un progetto di codice Google Autumn Framework .

Ma la risposta di tvanfosson è ciò che suggerirei di provare prima, prima di adottare un nuovo framework.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top