C#中的适配器模式

时间:2017-04-20 19:32:06

标签: c# design-patterns adapter

我想知道我是否正确理解了这种模式。让我们假设我们有接口不兼容。 来自第三方dll的函数Printer()需要IHPPrinter,但是我们的对象没有实现这种干扰......所以最后我们必须实现这个接口并返回我们的方法实现,如下面的代码? :) 第二个问题是,如果我们不提供方法DocumentsInQueue的实现,则会抛出异常。是否有可能阻止调用此方法?

class Program
{
    static void Main(string[] args)
    {
        EpsonPrinter _epsonPrinter = new EpsonPrinter();
        Printer(_epsonPrinter);
        Console.ReadKey();
    }


    public static void Printer(IHPPrinter hpPrinter)
    {
        hpPrinter.PrintDocument();
    }

    public interface IHPPrinter
    {
        void PrintDocument();
        int DocumentsInQueue();
    }
    public interface IEpsonPrinter
    {
        void Print();
    }

    public class EpsonPrinter : IEpsonPrinter, IHPPrinter
    {
        public int DocumentsInQueue()
        {
            throw new NotImplementedException();
        }

        public void Print()
        {
            this.PrintDocument();
        }

        public void PrintDocument()
        {
            Console.WriteLine("Printing from Epson printer...");
        }


    }
}

2 个答案:

答案 0 :(得分:2)

您提供的代码不是适配器模式的示例。

您的示例的适配器将是它自己的类,可能类似于EpsonPrinterToHpPrinterAdapter。它将实现IHPPrinter并将IEpsonPrinter实现的实例作为其构造函数的参数。

然后,您将EpsonPrinterToHpPrinterAdapter的实例传递给期望IHPPrinter的方法。然后,适配器类将从IHPPrinter方法的所有调用转换为从构造函数调用IEpsonPrinter的引用。

适配器模式的主要目标是通过尽可能最好地将行为从一个转换为另一个来使类B像类A一样运行。你不能阻止一个成员被调用,你必须提供某种特殊的实现,它将适用于你正在适应的类。

在您的具体示例中,将PrintDocument的调用直接传递给Print会非常简单,但调用DocumentsInQueue会更加困难,因为没有匹配的成员在IEpsonPrinter。您可能需要单独跟踪和返回计数,每次调用PrintDocument时递增内部计数器,并在完成时递减计数。

当您不控制这些代码的所有部分时,这种类型的模式变得非常重要。如果EpsonPrinterPrinter类都在您无法修改的第三方库中定义,则可以使用此模式将它们连接在一起。

我已经采用了您的示例并进行了使用适配器模式所需的更改:

class Program
    {
        static void Main(string[] args)
        {
            EpsonPrinter epsonPrinter = new EpsonPrinter();
            EpsonPrinterToHPPrinterAdapter adapter = new EpsonPrinterToHPPrinterAdapter(epsonPrinter);
            Printer(adapter);
            Console.ReadKey();
        }


        public static void Printer(IHPPrinter hpPrinter)
        {
            hpPrinter.PrintDocument();
        }

        public interface IHPPrinter
        {
            void PrintDocument();
            int DocumentsInQueue();
        }
        public interface IEpsonPrinter
        {
            void Print();
        }

        public class EpsonPrinterToHPPrinterAdapter :  IHPPrinter
        {

            public EpsonPrinterToHPPrinterAdapter(IEpsonPrinter epsonPrinter)
            {
                EpsonPrinter = epsonPrinter;
                _queueCount = 0;
            }

            private int _queueCount;

            public IEpsonPrinter EpsonPrinter { get; }

            public void PrintDocument()
            {
                _queueCount++;
                EpsonPrinter.Print();
                _queueCount--;
            }

            public int DocumentsInQueue()
            {
                return _queueCount;
            }
        }

        public class EpsonPrinter : IEpsonPrinter
        {
            public void Print()
            {
                Console.WriteLine("Printing from Epson printer...");
            }
        }
    }

答案 1 :(得分:1)

来自Interfaces (C# Programming Guide)

  

当类或结构实现接口时,类或结构必须为接口定义的所有成员提供实现。

您无法阻止调用DocumentsInQueue()。如果你没有实现它,你应该抛出NotSupportedException

  

抛出NotSupportedException异常

     

您从一个抽象类继承,要求您覆盖许多方法。但是,您只准备为其中一部分提供实施。对于您决定不实现的方法,可以选择抛出NotSupportedException。

例如:

public int DocumentsInQueue()
{
    throw new NotSupportedException("DocumentsInQueue is not supported in EpsonPrinter.");
}