适配器设计模式如何在C#中工作?

时间:2013-03-14 15:35:32

标签: c# design-patterns adapter

我在这里有一个适配器模式的例子(是的,你可以检查它是否已正确实现),但我真正的问题在这里,据说适配器设计模式执行以下操作:“将类的接口转换为客户期望的另一个接口。适配器允许类一起工作,否则由于不兼容的接口而无法工作。“但是我对这个声明感到有点困惑,我根据下面的代码不太了解,我想知道它发生在哪里。

以下是我的课程/界面:

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();
     }
 }

4 个答案:

答案 0 :(得分:3)

您的代码显示了适配器,但未显示使用将其作为适配器。

要使用此适配器,您需要通过适配器将实现LogRepository的{​​{1}}用作IRepository<Log>。类似的东西:

ILogger

答案 1 :(得分:2)

用简单的话说 -

  1. 重命名您的适配器,因为它实际上不是InfrastructureLoggerToDatabaseAdapter而是它的Repository to Logger类型。由于您传递的是IRepository类型的对象,并期望它的行为类似于ILogger。

  2. 由于存储库现已更新转换为ILog类型对象,因此应使用ILogger变量对其进行操作。

  3. 代码:

    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();
            }
        }
    

    希望这是有道理的。如果有什么不清楚,请告诉我。

答案 2 :(得分:1)

  

将类的接口转换为客户期望的另一个接口。适配器允许类一起工作,否则由于不兼容的接口而无法使用。

在这种情况下,您有IRepository<Log>,但您需要成为ILogger,即“客户期望的其他界面”。适配器类通过封装IRepository<Log>并将ILogger次调用转换为IRepository<Log>次调用来实现此目的。

答案 3 :(得分: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没有实现ILogger接口。但是使用适配器,您可以将IRepository<Log>接口转换为ILogger类所需的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课程仍在完成实际工作。适配器只是将其接口调整为客户端所需的接口。插座适配器的工作原理相同如果你的电动剃须刀应该插在美国插座上,你就不能在没有适配器的欧洲使用它。