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

本文关键字:工作 设计模式 适配器 | 更新日期: 2023-09-27 18:03:50

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

这是我的类/接口:

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

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

您的代码显示了适配器,但没有显示使用作为适配器。

为了使用这个适配器,您需要使用您的LogRepository,它通过适配器实现IRepository<Log>作为ILogger。比如:

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

用简单的话来说-

  1. 重命名你的适配器,因为它不是一个真正的InfrastructureLoggerToDatabaseAdapter,而是一个Repository to Logger类型。因为你正在传递一个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();
        }
    }

希望这是有意义的。如果有什么不清楚的地方请告诉我。

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

在这种情况下,你有一个IRepository<Log>,但你需要成为一个ILogger,即。"另一个客户端期望的接口"。适配器类通过封装IRepository<Log>并将ILogger调用转换为IRepository<Log>调用来实现这一点。

从您的示例中不清楚,因为您没有需要logger的客户端。考虑下面的类:

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>接口"转换"为Foo类所需的ILogger接口:

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班完成。适配器只是将它的接口适配到客户端所需的接口。与插座适配器的工作方式相同。如果你的电动剃须刀应该插在美国的插座上,如果没有适配器,你就不能在欧洲使用。