2013-03-14 59 views
2

我在這裏有一個適配器模式的例子(是的,你可以檢查它是否正確實現),但我真正的問題是在這裏,據說適配器設計模式執行以下操作:「將類的接口轉換爲另一個接口客戶端期望。適配器讓類能夠協同工作,否則因爲不兼容的接口而無法工作。「但是我對這個陳述有點困惑,我不完全基於我的代碼,我想知道它發生在哪裏。適配器設計模式在C#中如何工作?

這裏是我的類/接口:

public interface ILogger 
{ 
     void Write(string data); 
} 

public class InfrastructureDebugLogger : ILogger 
{ 
     public void Write(string data) 
     { 
      Debug.WriteLine(data); 
     } 
} 

public class InfrastructureLoggerToDatabaseAdapter : ILogger 
{ 
     private IRepository<Log> adaptee; 

     public InfrastructureLoggerToDatabaseAdapter(IRepository<Log> adaptee) 
     { 
      this.adaptee = adaptee; 
     } 

     public void Write(string data) 
     { 
      var log = new Log() { Value = data }; 
      adaptee.Create(log); 
     } 
} 

public interface IRepository<T> 
{ 
     void Create(T item); 
     void Update(T item); 
     T Find(int id); 

} 

public class Log 
{ 
     public int ID { get; set; } 
     public string Value { get; set; } 
} 

public class LogRepository : IRepository<Log> 
{ 
     public void Create(Log item) 
     { 
      Console.WriteLine("Created an item inside the LogRepository"); 
     } 

     public void Update(Log item) 
     { 
      throw new NotImplementedException(); 
     } 

     public Log Find(int id) 
     { 
      throw new NotImplementedException(); 
     } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 

      ILogger logger = new InfrastructureDebugLogger(); 
      Console.Write("Data: "); 
      string data = Console.ReadLine(); 
      logger.Write(data); 
      InfrastructureLoggerToDatabaseAdapter loggerToDatabaseAdapter = 
       new InfrastructureLoggerToDatabaseAdapter(new LogRepository()); 
      loggerToDatabaseAdapter.Write(data); 
      Console.ReadKey(); 
    } 
} 
+0

您的適配器InfrastructureLoggerToDatabaseAdapter實際上命名不正確。它正在接收一個IRepository類型的對象並將其轉換爲一個ILogger類型。所以它實際上應該被稱爲DatabaseToInfrastructureLoggerAdapter或者更確切地說是RepositoryToLoggerAdapter。 – Tushar 2013-03-14 15:47:36

回答

2

說得簡單的話 -

  1. 重命名你的適配器,因爲它不是一個真正的InfrastructureLoggerToDatabaseAdapter而不是它的庫到記錄器類型。由於您傳遞了一個IRepository類型的對象,並期望它的行爲像一個ILogger。

  2. 由於存儲庫現在已更新轉換爲ILog類型對象,因此應使用ILogger變量對其進行操作。

代碼:

public class RepositoryToLoggerAdapter : ILogger 
    { 
     private IRepository adaptee; 

     public InfrastructureLoggerToDatabaseAdapter(IRepository adaptee) 
     { 
      this.adaptee = adaptee; 
     } 

     public void Write(string data) 
     { 
      var log = new Log() { Value = data }; 
      adaptee.Create(log); 
     } 
    } 

class Program 
    { 
     static void Main(string[] args) 
     { 

      ILogger logger = new InfrastructureDebugLogger(); 
      Console.Write("Data: "); 

      string data = Console.ReadLine(); 

     //This step is redundant as the text will be shown on the screen as you type 
logger.Write(data); 

//Create an object of IRepository type. 
IRepository repository= new LogRepository(); 

//The create method works as it should 
repository.Create(data); 


//You could not have stored the repository object in the logger variable if you did not have this adapter. 

      logger = new RepositoryToLoggerAdapter(repository); 

//Effectively you now are calling the Create method of the Repository by calling the Write method of the logger. 

      logger.Write(data); 
      Console.ReadKey(); 
     } 
    } 

希望這是有道理的。如果有什麼不清楚,請告訴我。

+0

謝謝你的解決方案,它被解釋得非常好。只是有一個問題,如果我做這樣的事情會有區別:logger = new RepositoryToLoggerAdapter(new LogRepository()),因爲LogRepository實現了IRepository? – 2013-03-14 16:50:33

+1

一定要繼續。我只是寫了它,以便更容易理解。 – Tushar 2013-03-14 16:58:15

3

你的代碼顯示適配器,但使用它作爲一個適配器不顯示

爲了使用此適配器,您需要通過適配器將您的LogRepository(其實現IRepository<Log>)用作​​。例如:

class Program 
{ 
    static void Main(string[] args) 
    { 

     Console.Write("Data: "); 
     string data = Console.ReadLine(); 
     InfrastructureLoggerToDatabaseAdapter loggerToDatabaseAdapter = 
      new InfrastructureLoggerToDatabaseAdapter(new LogRepository()); 

     // Here, you're using a IRepository<Log>, but adapting it to be used as an ILogger... 
     ILogger logger = loggerToDatabaseAdapter; 
     logger.Write(data); 
     Console.ReadKey(); 
    } 
} 
0

從您的示例中不清楚,因爲您沒有客戶端需要記錄器。考慮以下課程:

public class Foo 
{ 
    private ILogger _logger; 

    public Foo(ILogger logger) 
    { 
     _logger = logger; 
    } 

    public void Bar() 
    { 
     _logger.Write("Bar is called"); 
     // do something 
    } 
} 

您無法將LogRepository傳遞給此類。因爲LogRepository未實現​​接口。但隨着適配器可以「轉換」 IRepository<Log>接口由Foo類所需​​接口:

class Program 
{ 
    static void Main(string[] args) 
    { 
     // you can't pass repository to Foo 
     LogRepository repository = new LogRepository();    

     InfrastructureLoggerToDatabaseAdapter loggerToDatabaseAdapter = 
      new InfrastructureLoggerToDatabaseAdapter(repository); 

     // but you can pass adapter 
     Foo foo = new Foo(loggerToDatabaseAdapter); 
     foo.Bar(); 

     Console.ReadKey(); 
    } 
} 

實際工作仍由LogRepository類完成。適配器只是將其接口適配到客戶端所需的接口。同樣的方式出口適配器的工作。如果您的電動剃鬚刀應插入美國插座,則不能在沒有適配器的歐洲使用。

1

將類的接口轉換爲客戶端期望的另一個接口。適配器讓類可以協同工作,否則就會因爲不兼容的接口而無法工作。

在這種情況下,您有IRepository<Log>,但您需要成爲​​,即「另一個接口客戶端期望」。適配器類允許通過封裝IRepository<Log>並將​​調用轉換爲IRepository<Log>調用。