Principio aperto / chiuso

2

Ho trovato questo esempio di codice che spiega il principio Open / Closed .

Codice prima dell'applicazione del principio:

public class Logger
{
    public void Log(string message, LogType logType)
    {
        switch (logType)
        {
            case LogType.Console:
                Console.WriteLine(message);
                break;

            case LogType.File:
                // Code to send message to printer
                break;
        }
    }
}

public enum LogType
{
    Console,
    File
}

E codice refactored:

public class Logger
{
    IMessageLogger _messageLogger;

    public Logger(IMessageLogger messageLogger)
    {
        _messageLogger = messageLogger;
    }

    public void Log(string message)
    {
        _messageLogger.Log(message);
    }
}

public interface IMessageLogger
{
    void Log(string message);
}    

public class ConsoleLogger : IMessageLogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}

public class PrinterLogger : IMessageLogger
{
    public void Log(string message)
    {
        // Code to send message to printer
    }
}

Puoi spiegarmi il motivo per mantenere ancora Logger class con private IMessageLogger istanza? Lo eviterei semplicemente:

public interface ILogger
{
    public void Log(string message);
}

public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}    

public class PrinterLogger : ILogger
{
    public void Log(string message)
    {
        // Code to send message to printer
    }
}

L'unica ragione per cui posso pensare è che nella soluzione suggerita con Logger class, potremmo ancora fare riferimento a questa classe nel codice client, ma dobbiamo ancora modificare tutte le chiamate Log(msg) per rimuovere gli argomenti LogType .

    
posta Majak 05.02.2016 - 10:36
fonte

1 risposta

5

Finché la nuova classe Logger non contiene più codice, l'esempio sembra essere forzato. Ma immagina che la classe ottenga altri metodi, con un codice indipendente dal concreto IMessageLogger , ad esempio:

public class Logger
{
    // ...
    public void LogFormatted(string formatString, string[] parameters )
    {
        string message = string.Format(formatString, parameters);
        _messageLogger.Log(message);
    }
}

Quindi ha senso avere una classe in cui è possibile implementare questo codice aggiuntivo un posto, mantenendo il programma ASCIUTTO.

Lo schema che vediamo qui è il classico schema di "strategia". Ciò diventa ovvio quando si rinomina IMessageLogger in ILoggingStrategy e le classi derivate in ConsoleLoggingStrategy e PrinterLoggingStrategy .

È anche una dimostrazione dell'OCP, perché ora puoi mettere Logger e IMessageLogger (o ILoggingStrategy ) in una libreria (o framework) riutilizzabile, mentre le nuove derivazioni IMessageLogger possono risiedere nel codice dell'applicazione usando quella lib Quindi la lib, inclusa la classe Logger , non dovrà essere modificata se qualcuno vuole aggiungere qualcosa come una nuova strategia come CloudLoggingStrategy , per esempio. Nel codice originale, tuttavia, una lib contenente la classe Logger dovrebbe essere modificata per tale estensione.

    
risposta data 05.02.2016 - 13:00
fonte

Leggi altre domande sui tag