Supponiamo di definire due interfacce di seguito:
public interface IReader
{
void Read(string bookName);
}
public interface IWriter
{
void Write(string bookName);
}
Ora voglio implementare l'interfaccia IReader in questo modo:
public class Reader : IReader
{
private IEnumerable<string> _books;
public Reader(IEnumerable<string> books)
{
_books = books; // List of books is given through constructor
}
public void Read(string bookName)
{
if (_books.Contains(bookName))
{
// Reading here
}
else
{
throw new InvalidOperationException("Given book name was not found in the library.");
}
}
}
E ora voglio definire una classe di livello superiore che implementa entrambe le due interfacce:
public class Person : IReader, IWriter
{
// This is the data I want to share with IReader argument of constructor
private IList<string> _books = new List<string>();
private IReader _reader;
public Person(IReader reader)
{
_reader = reader; // How do I share books with this object?
}
public void Read(string bookName)
{
_reader.Read(bookName);
}
public void Write(string bookName)
{
_books.Add(bookName);
}
}
Come hai notato, ho usato la composizione per implementare l'interfaccia IReader. Devo inserire un'istanza di Reader nella classe Person ma devo anche condividere i dati dei libri della mia persona con l'istanza Reader. Questo è il problema che voglio risolvere.
Finora non abbiamo fornito un modo per condividere l'elenco di libri con l'interfaccia IReader. Mi vengono in mente alcune opzioni:
Prima opzione: crea un'interfaccia IReaderFactory e la sua implementazione che crea un'istanza come questa:
public interface IReaderFactory
{
IReader Create(IEnumerable<string> books);
}
public class ReaderFactory : IReaderFactory
{
public IReader Create(IEnumerable<string> books)
{
return new Reader(books);
}
}
Questo è tutto ok, ora posso iniettare IReaderFactory nel mio costruttore Person anziché in IReader. Il rovescio della medaglia è che richiede 2 definizioni aggiuntive IReaderFactory e ReaderFactory.
Seconda opzione: aggiungi un altro metodo all'interfaccia IReader in questo modo:
void Initialize(IEnumreable<string> books);
Anche questo funziona, nel costruttore di Person posso chiamare questo metodo e passare i miei libri ad esso. Ma non mi sembra elegante, perché ora devo ricordare chiamare questo metodo e questo metodo può essere chiamato più volte , che è qualcosa che non desiderare.
Non voglio usare un contenitore DI e risolvere un'istanza di IReader all'interno del costruttore di Person perché nasconde le dipendenze della classe Person.
Ora, qual è il modo migliore per andare in questo tipo di situazione senza violare Principio di inversione delle dipendenze ?