接口

问题的提出
定义:开发一个应用,使不同型号的打印机都能与电脑连接
上下文(环境):为了满足需求,公司现在购置了两类打印机,即打印机A和打印机B,它将与公司1000名员工的电脑连接,实现通信。并且公司在以后可能还会购买第三类打印机。
分析上述问题,可能有如下方案
方案一:分别定义PrintA和PrintB两个类。实现各自的Receive和Print方法,这么一来总共需要写四个方法。这种方法应该是最直观,最容易让人想到的。
方案二:定义抽象类Printer,在里面写虚方法 Receive和 Print,使得这两台打印机分别继承此抽象类,并重写 Receive和Print方法。Computer类中包含一个类型为 Printer的成员变量,并为其编写get/set器,这样 Computer中只需要两个方法: ReceiveData和 PrintData,并通过多态性实现不同移动设备的读写。这种方法应该是接着会被想到的方法。
方案三:与方案二基本相同,只是不定义抽象类,而是定义接口I Printer,修改打印机类。Computer中通过依赖接口IPrinter实现多态性。
       现在我们来分析一下上面三种方法。首先第一种方法最为直白,实现起来最简单,但是它有一个致命的弱点:可扩展性差。当将来有了第三中类型的打印机时,必须对Computer进行修改。这就如在一个真实的计算机上,为每一种打印机设备实现一个不同的插口、并分别有各自的驱动程序。当有了一种新的打印机设备后,我们就要将计算机大卸八块,然后增加一个新的插口,在编写一套针对此新设备的驱动程序。这种设计显 然不可取。

  此方案的另一个缺点在于,冗余代码多。在题目所给的环境中,已经说明打印机将与1000台电脑连接,这么一来,总共就需要写四千中方法。代码的重复量是相当大的。我们再来看方案二和方案三,之所以将这两个方案放在一起讨论,是因为他们基本是一个方案(从思想层面上来说),只不过实现手段不同,一个是使用了抽象类,一个是使用了接口,而且最终达到的目的应该是一样的。

  我们先来评价这种方案:首先它解决了代码冗余的问题,因为可以动态替换打印机,并且都实现了共同的接口,所以不管有多少种移不同类型的打印机,只要一个 Receive方法和一个Print方法,多态性就帮我们解决问题了。而对第一个问题,由于可以运行时动态替换,而不必将打印类编码在Computer 中,所以有了新的第三方设备,完全可以替换进去运行。这就是所谓的“依赖接口,而不是依赖于具体类”。如此一来,Computer和打印机类的耦合度大大下降。

我们先来看一段断码:

1.定义一个接口

namespace _1.InterfaceTest

{

     /// <summary>

     /// 定义打印机接口,不同类型的打印机都有共同的属性

     /// 他们都会接受电脑的信息(Receive)并且执行打印命令(Print)。

     /// </summary>

     public interface IPrinter

     {

        void Receive();

        void Print();

     }

}

2. 实现打印机类

namespace _1.InterfaceTest

{

  /// <summary>
    /// 实现A类打印机
    /// </summary>
    public class PrinterA : IPrinter
    {
        /// <summary>
        /// 实现接口定义的Receive方法
        /// </summary>
        public void Receive()
        {
            Console.WriteLine("PrinterA  receive message from Computer……");
            Console.WriteLine("Receive finished!");
        }
        /// <summary>
        ///  实现接口定义的Print方法
        /// </summary>
        public void Print()
        {
            Console.WriteLine("PrinterA execute the Computer command ……");
            Console.WriteLine("Print finished!");
        }
    }
    /// <summary>
    /// 实现B类打印机
    /// </summary>
    public class PrinterB : IPrinter
    {
        /// <summary>
        /// 实现接口定义的Receive方法
        /// </summary>
        public void Receive()
        {
            Console.WriteLine("PrinterB  receive message from Computer……");
            Console.WriteLine("Receive finished!");
        }
        /// <summary>
        ///  实现接口定义的Print方法
        /// </summary>
        public void Print()
        {
            Console.WriteLine("PrinterB execute the Computer command ……");
            Console.WriteLine("Print finished!");
        }
    }
}
3. 实现computer类

namespace _1.InterfaceTest

{

  /// <summary>
    /// 电脑与打印机连接,不论是何种打印机,电脑都将调用这两个方法
    /// </summary>
    public class Computer
    {
        /// <summary>
        /// 定义接口类型的变量
        /// </summary>
        private IPrinter _print;
        public IPrinter Print
        {
            get
            {
                return this._print;
            }
            set
            {
                this._print = value;
            }
        }
        public Computer()
        {
        }
        public Computer(IPrinter print)
        {
            this.Print = print;
        }
        public void ReceiveData()
        {
            this._print.Receive();
        }
        public void PrintData()
        {
            this._print.Print();
        }
    }
 }
}
4.测试一下打印机是否能正常工作:
namespace _1.InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Computer computer = new Computer();
            IPrinter printerA = new PrinterA();
            IPrinter printerB = new PrinterB();
            Console.WriteLine("I connected  PrinterA into computer and print something");
            computer.Print = printerA;
            computer.ReceiveData();
            computer.PrintData();
            Console.WriteLine("-------------------------------------------------------------“);
            Console.WriteLine("Now,PrinterA has some problem!I connected  PrinterB into computer and print something");
            computer.Print = printerB;
            computer.ReceiveData();
            computer.PrintData();
     
        }
    }
}
输出结果:
测试成功!
此时又有另外一个问题,公司又重新购置了一台不同类型的打印机,那又该如何实现呢?过程简单。代码如下:
namespace _1.InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Computer computer = new Computer();
            IPrinter newPrinter = new NewPrinter();
            Console.WriteLine("I connected  newPrinter into computer and print something");
            computer.Print = newPrinter;
            computer.ReceiveData();
            computer.PrintData();
            Console.ReadLine();
     
        }
    }
}
运行截图:
哈哈,是不是很神奇,Computer一点都不用改动,就可以使新的设备正常运行。这就是所谓“对扩展开放,对修改关闭”。 
posted @ 2016-02-26 13:27  白衣秀才  阅读(323)  评论(0编辑  收藏  举报