私は多分、私はいくつかのポイントを欠けている、建築といくつかの問題をしたDI Iを勉強しています。
私は、この非DIのコードを持っていると仮定し(私は、ファイルから「人」のリストを読みます)
static void Main()
{
PersonReaderFromFile personReader = new PersonReaderFromFile("path-to-file");
Person p = personReader.GetNext(); //return a Person parsed from file line or NULL at EOF
}
class Person
{
//stuffs here
}
class PersonReaderFromFile
{
public Person GetNext()
{
Person person = new Person();
//some logic
return person;
}
}
私がやるので、まず、DIパターンを実現するために、私は、インターフェイスが必要
static void Main()
{
iPersonReader personReader = new PersonReaderFromFile("path-to-file");
iPerson p = personReader.GetNext();
}
interface iPerson
{
}
class Person : iPerson
{
}
interface iPersonReader
{
iPerson GetNext();
}
class PersonReaderFromFile : iPersonReader
{
public iPerson GetNext()
{
Person person = new Person();
//some logic
return person;
}
}
そして今、私の問題:PersonReaderFromFileは人の実装に依存します。大丈夫です?それとも私がPersonFactoryのように、余分なクラスが必要?
static void Main()
{
iPersonFactory factory = new PersonFactory();
iPersonReader personReader = new PersonReaderFromFile("path-to-file", factory);
iPerson person = personReader.GetNext();
}
interface iPerson
{
}
class Person : iPerson
{
}
interface iPersonReader
{
iPerson GetNext();
}
class PersonReaderFromFile : iPersonReader
{
iPersonFactory _factory;
public PersonReaderFromFile(iPersonFactory factory)
{
_factory = factory;
}
public iPerson GetNext()
{
Person person = _factory.CreateNewPerson();
//some logic
return person;
}
}
interface iPersonFactory
{
iPerson CreateNewPerson();
}
class PersonFactory : iPersonFactory
{
iPerson CreateNewPerson()
{
Person person = new Person();
return person;
}
}
今PersonFactoryは人の実装に依存しますが、それは正しいはずです。何かアドバイス?すべてのTNX。
編集:私は、サンプルPersonReaderFromFile実装を示し、
class PersonReaderFromFile
{
StreamReader _fileReader;
public PersonReaderFromFile(string path)
{
_fileReader = new StreamReader(file);
}
public Person GetNext()
{
string line = _fileReader.ReadLine();
if (line == null)
{
_fileReader.Close();
return null;
}
string name, lastName, email;
ParseInformationFromLine(line, out name, out lastName, out email);
Person p = new Person { Name = name, LastName = lastName, Email = email };
return p;
}
private ParseInformationFromLine(string line, out string name, out string lastName, out string email)
{
//I don't think that matters
}
}
PersonReaderFromFile
依存しませんPerson
。そのクラスは、実行時データを表しちょうどPOCOように見えます。
PersonReaderFromFile
依存しているStreamReader
とともにParseInformationFromLine
機能
自分の関心事にそれらの実装の詳細アウトまず抽象的。
public interface IReadLines {
string ReadLine();
}
public interface IParsePersonInformationFromLine {
void ParseInformationFromLine(string line, out string name, out string lastName, out string email);
}
ターゲットクラスは、明示的に抽象化に依存するであろう
public class PersonReaderFromFile {
private readonly IReadLines reader;
private readonly IParsePersonInformationFromLine parser;
public PersonReaderFromFile(IReadLines reader, IParsePersonInformationFromLine parser) {
this.reader = reader;
this.parser = parser;
}
public Person GetNext() {
string line = reader.ReadLine();
if (line == null) {
return null;
}
string name, lastName, email;
parser.ParseInformationFromLine(line, out name, out lastName, out email);
Person p = new Person { Name = name, LastName = lastName, Email = email };
return p;
}
}
個々の抽象化は、実行時に使用される所望の機能性を満たすために、独自の実装を持っているでしょう。たとえば、読者は内部でまだ使用するStreamReader
ラインを取得します。PersonReaderFromFile
行を取得する方法について何を知っている必要はありません。呼び出されたときには、ラインを望んでいるだけのこと。
Main
今例えばピュアDIを使用するようにリファクタリングすることができます
static void Main() {
IReadLines reader = new ReadLinesImplementation("path-to-file");
IParsePersonInformationFromLine parser = new ParsePersonInformationFromLine();
PersonReaderFromFile personReader = new PersonReaderFromFile(reader, parser);
Person p = personReader.GetNext(); //return a Person parsed from file line or NULL at EOF
}
適用することができるが、これだけしっかりと実装の問題に連結されるコードの抽象化されるべき特定の実装の詳細の単純化した例であることを意味するさらなるリファクタリングがあります。