Quale modello di progettazione per un segnalatore

-1

Sto davvero lottando per trovare un modello di design per un Alerter che sto costruendo. Ecco un esempio forzato di ciò che sto cercando di fare:

Una persona desidera ricevere un avviso in base al tipo di clima (pioggia, neve, sole, ecc.). Una persona ha anche una scelta di metodi di allerta (email, sms, canale allentato, chat room, ecc.)

Ho bisogno di: avere una lezione che includa un tipo di clima. Quindi recupera tutte le persone che si interessano a quel tipo di tempo. Quindi scorre attraverso tutte le persone e invia loro il loro avviso (in base alla preferenza del tipo di avviso della persona).

Sto cercando di stare lontano dall'odore delle istruzioni switch, ma forse non è così brutto come sembra?

Ecco il mio schema di base, ma sembra che dovrebbe essere fatto "meglio":

public class Alerter
{
    private readonly WeatherType _weatherType;

    public Alerter(WeatherType weatherType)
    {
        _weatherType = weatherType;
    }

    public void SendAlerts()
    {
        var people = PersonRepository.GetPeople(_weatherType);

        foreach (Person person in people)
        {
            switch (person.AlertType)
            {
                case Email:
                    var e = new EmailAlerter();
                    e.SendToPerson(person, _weatherType);
                    return;
                case SMS:
                    var s = new SmsAlerter();
                    s.SendToPerson(person, _weatherType);
                    return;
            }
        }
    }
}
    
posta Matt 24.09.2016 - 15:17
fonte

2 risposte

2
var people = PersonRepository.GetPeople(_weatherType);

La prima cosa da notare è che stai usando un localizzatore di servizi qui, che è ampiamente riconosciuto come anti-pattern. Pertanto, puoi migliorarlo iniettando un'istanza di IPersonRepository nel costruttore di Alerter .

switch (person.AlertType)
{
    case Email:
        ...
}

L'istruzione switch ha un sacco di codice duplicato poiché ogni caso seleziona un tipo e invoca SendToPerson per quel tipo. Questo potrebbe essere sostituito con una factory (iniettata tramite il costruttore, ovviamente) che restituisce un'istanza di IAlerter e il metodo SendToPerson chiamato su quello:

public void SendAlerts()
{
    var people = _personRepository.GetPeople(_weatherType);

    foreach (var person in people)
    {
        var alerter = _alerterFactory(person.AlertType);
        alerter.SendToPerson(person, _weatherType);
    }
}

(nota, ho assunto che il return sia un errore nel tuo codice, altrimenti avviserebbe sempre la prima persona.)

    
risposta data 25.09.2016 - 23:00
fonte
-2

Poiché ogni utente ha il proprio metodo di avviso preferito (probabilmente proveniente da alcune impostazioni utente), questa informazione appartiene all'utente (= dovrebbe essere parte dello stato interno dell'utente, come attributo). Gli oggetti User devono essere responsabili per decidere come inviare gli avvisi e deve essere opaco per il chiamante.

public void SendAlerts()
{
    var people = PersonRepository.GetPeople(_weatherType);

    foreach (Person person in people)
    {
        person.send(_weatherType); //inside it's using EmailAlerter, SmsAlerter, etc.
    }
}

In questo modo, ti libererai di qualsiasi interruttore. Si noti che non sto utilizzando alcun modello di progettazione (eccezione forse iniezione di dipendenza).

I modelli di progettazione non sono una pallottola d'argento: sono buoni servi ma cattivi maestri. Non lasciare che tutte le tue decisioni di progettazione siano guidate da loro, ma usale solo quando affronti un problema che un modello di design ha già risolto.

    
risposta data 26.09.2016 - 09:12
fonte

Leggi altre domande sui tag