2

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

这是我的课程/界面:

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

4 回答 4

3

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

为了使用这个适配器,你需要使用你的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();
    }
}
于 2013-03-14T15:39:03.233 回答
2

用简单的话来说——

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

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

于 2013-03-14T16:05:36.540 回答
1

将类的接口转换为客户期望的另一个接口。Adapter 让那些因为接口不兼容而无法协同工作的类。

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

于 2013-03-14T15:39:36.033 回答
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班级完成。适配器只是将其接口调整为客户端所需的接口。插座适配器的工作方式相同。如果你有电动剃须刀,应该插入美国插座,你不能在没有适配器的情况下在欧洲使用它。

于 2013-03-14T15:39:13.760 回答