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ではなく、RepositorytoLoggerタイプであるためです。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

クラスのインターフェースを、クライアントが期待する別のインターフェースに変換します。アダプタを使用すると、インターフェイスに互換性がないために他の方法では機能しなかったクラスを連携させることができます。

この場合、あなたはを持っていますが、あなたは、すなわち「クライアントが期待する別のインターフェース」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>ILoggerFoo

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 に答える