论文部分内容阅读
摘 要:面向對象的设计思想,有三个重要的组成部分,封装、继承和多态,封装是基础,继承是关键,多态是延伸。多态是指相同的语法结构可以代表不同类型的实体或者对不同类型的实体进行操作,即发出同样的消息被不同对象接收时导致完全不同的行为,而实现多态中,一个重要的手段就是面向接口的思想方法。本文通过一个实例来讲解接口如何实现方法的多态。
关键词:面向对象;多态;接口
1、引言
在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务,即不是直接实例化在上层中,而是通过定义一组接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体类[1]。如何才能做到层次分明,如何才能做到软件开发的低耦合、高内聚的设计要求,其中就用到了面向对象软件设计思想之一的面向接口(interface)思想,用到的关键技术是接口技术。
2、定义
接口的概念是定义与实现的分离[2]。
所谓的定义,就是指一组规则的集合,它规定了实现本接口的类或接口必须拥有的一组规则,通俗的讲,就是接口只是规定了要完成的功能,或是提供的功能,而不是这个接口的实现的算法或过程。比如,我们家里的电灯泡坏了,那么我们只需要到市场上买一个电灯泡就可以了,而不需要考虑是什么样的灯泡,因为几乎所有的灯泡都是一样的接口。在这里面蕴含着接口的思想。工业界已经就电灯泡和插座之间接触的直径都做了规定,必须是多少毫米的直径,那么所有制造灯泡插座的厂家就按这个标准去做灯泡插座,而造灯泡的厂家按照这个标准去生产灯泡,而不用关心这个灯泡的形状、效能等,因为只要接触的地方是要求的大小就可以了。这里就是接口的标准应用。在实现一个软件系统的时候,通常是系统架构师对系统进行分层,定义每一层之间的接口,每一层通过接口对上层进行提供服务,保证所有的定义与实现分离,这样做,可以保证底层的修改不会影响上一层的运行,
因为已经做到了依赖的最小化。
3、程序模拟
在我们软件的设计过程中,要充分理解和利用接口思想,Martin Fowler[3]在他的《分析模式》一书中指出,分析问题应该站在概念的层次上,而不是站在实现的层次上。所谓的概念层次,就是分析对象该做什么,而不是分析对象怎么做。下面将一个例子来体会。假如有一个老李想加密一个字符串,要求可以根据不同的条件使用不同的方法。在这里,我们使用C#来编写这个需求模拟程序,在VS2005里,新建一个控制台应用程序,
首先引入的要用的命名空间,如下。
using System;
using System.Collections.Generic;
using System.Text;
然后,我们定义一个接口,这个接口规定了要进行加密和解密的通用方法,这里相当于水管和水龙头接触之间的直径大小的规定。
public interface ICryptography
{
string EncryptString(string strNeed2Enc, string key);
string DecryptString(string strNeed2Dec, string key);}
其中方法EncryptString用来进行数据的加密,输入的参数是要进行加密的数据和密钥,返回的是加密之后的数据。方法DecryptString用于数据的解密,参数为要进行解密的数据和密钥。
然后我们编写了两个类,每个类都继承了这个接口,即我们的实现类中都对这个接口中定义的函数进行了实现,对外可以提供相同的方法名和参数。
下面是第一个类FirstCrypt,对这个接口中的方法进行了简单的实现,对传入的参数进行简单的运算,只是在传入的数据和key之间加上了一个“+FirstCrypt+”,并进行了返回。在这里我们称之为加密吧;而另外的解密方法同样就是把这个加密后的值,进行了简单的解密,然后返回。
public class FirstCrypt : ICryptography
{public string EncryptString(string strNeed2Enc, string key)}
{string afterEnc=strNeed2Enc+"+FirstCrypt+"+key;
Console.WriteLine(“FirstCrypt类中的加密方法被调用!”);
return afterEnc;}
public string DecryptString(string strNeed2Dec, string key)
{int pos=strNeed2Dec.IndexOf(“+FirstCrypt+”);
string afterDec=strNeed2Dec.Substring(0,pos);
Console.WriteLine(“FirstCrypt类中的解密方法被调用!”);
return afterDec;}
同样,我们第二个集成了ICryptography接口的类,叫做SecondCrypt,这个类也简单的实现了一个加密和一个解密函数。同时,我们在每个函数中,加入了一个Console类的WriteLine方法的调用,在屏幕上显示现在正在执行的是哪一个语句。
public class SecondCrypt : ICryptography
{public string EncryptString(string strNeed2Enc, string key)}
{string afterEnc=strNeed2Enc+“+SecondCrypt+”+key;
Console.WriteLine(“SecondCrypt类中的加密方法被调用!”);
return afterEnc;}
public string DecryptString(string strNeed2Dec, string key)
{int pos=strNeed2Dec.IndexOf(“+SecondCrypt+”);
string afterDec=strNeed2Dec.Substring(0,pos);
Console.WriteLine(“SecondCrypt类中的解密方法被调用!”);
return afterDec;}

为了模拟老李加解密的需要,同时定义了一个Person类,用其来实例化一个老李,这个类中的一个重要成员,是ICryptography接口类型的m_iCryptObj,在调用的时候,在对这个变量赋值的时候,通过调用CryptObj属性,进行赋值;而Person类,对外提供一个加密和一个解密的方法。
public class Person
{private ICryptography m_iCryptObj;
public ICryptography CryptObj}
get { return m_iCryptObj;}
set {m_iCryptObj=value;}
public Person()
public Person(ICryptography crypt)
{m_iCryptObj = crypt;}
public string WantToCryptString(string str, string key)
{return this.m_iCryptObj.EncryptString(str, key);}
public string WantToDecryptString(string str, string key)
{return this.m_iCryptObj.DecryptString(str, key);}
在Main函数里,首先用类Person实例化一个laoli对象,用FirstCrypt类和SecondCrypt类分别实例化ICryptography 接口类型的firstCrypt对象和secondCrypt对象:
Person laoli = new Person();
ICryptography firstCrypt = new FirstCrypt();
ICryptography secondCrypt = new SecondCrypt();
然后,我们输出一行,标识老李用第一中方法进行加密,接下来很重要的一点是用firstCrypt给laoli的私有成员m_iCryptObj进行赋值,当然是通过CryptObj属性。
Console.WriteLine(“老李想用第一种方式加密:”);
laoli.CryptObj=firstCrypt;
在下面就是调用laoli本身的加解密方法进行加解密,并输出,这个时候调用的是第一种加解密方式:
string need2Enc=“我是老李”;
Console.WriteLine(“要加密的字符串为:”+need2Enc);
string retStr=laoli.WantToCryptString(need2Enc,“OK”);
Console.WriteLine(retStr);
Console.WriteLine(“老李想用第一种方式解密:”);
string beforEnc=laoli.WantToDecryptString(retStr,“OK”);
Console.WriteLine(“解密的字符串为:”+beforEnc);
在第二部分,laoli准备用第二种方式进行加解密,只需要调用laoli.CryptObj=secondCrypt就行了,相关代码如下:
Console.WriteLine(“老李想用第二種方式加密:”);
laoli.CryptObj=secondCrypt;
string need2Enc2=“我是老李”;
Console.WriteLine(“要加密的字符串为:”+need2Enc2);
string retStr2=laoli.WantToCryptString(need2Enc2,“OK”);
Console.WriteLine(retStr2);
Console.WriteLine(“老李想用第二种方式解密:”);
string beforEnc2=laoli.WantToDecryptString(retStr2,“OK”);
Console.WriteLine(“解密的字符串为:”+beforEnc2);
最后的运行结果,如图1:
通过图一,我们可以看出,在接口中声明了一些函数,
那么只要继承了这个接口的类或接口,那么就要实现这个接口中定义的函数。接口的定义唯一,而接口的实现却不唯一。所以,通过一些设计模式,可以达到动态的改变接口的实现,这里面就要用到工厂模式等。面向接口的编程,是面向对象编程思想中重要的一部分,深入理解面向接口的概念和作用,对提高软件的设计能力有很大的帮助。
参考文献:
[1]Bruce Eckel(美),陈昊鹏译,Java编程思想(第4版),机械工业出版社,2007年6月.
[2]程杰著,分析模式:可复用的对象模型,清华大学出版社,2007年12.
[3]Martin Fowler,樊东平张路译,分析模式,机械工业出版社,2004年1月.
关键词:面向对象;多态;接口
1、引言
在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务,即不是直接实例化在上层中,而是通过定义一组接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体类[1]。如何才能做到层次分明,如何才能做到软件开发的低耦合、高内聚的设计要求,其中就用到了面向对象软件设计思想之一的面向接口(interface)思想,用到的关键技术是接口技术。
2、定义
接口的概念是定义与实现的分离[2]。
所谓的定义,就是指一组规则的集合,它规定了实现本接口的类或接口必须拥有的一组规则,通俗的讲,就是接口只是规定了要完成的功能,或是提供的功能,而不是这个接口的实现的算法或过程。比如,我们家里的电灯泡坏了,那么我们只需要到市场上买一个电灯泡就可以了,而不需要考虑是什么样的灯泡,因为几乎所有的灯泡都是一样的接口。在这里面蕴含着接口的思想。工业界已经就电灯泡和插座之间接触的直径都做了规定,必须是多少毫米的直径,那么所有制造灯泡插座的厂家就按这个标准去做灯泡插座,而造灯泡的厂家按照这个标准去生产灯泡,而不用关心这个灯泡的形状、效能等,因为只要接触的地方是要求的大小就可以了。这里就是接口的标准应用。在实现一个软件系统的时候,通常是系统架构师对系统进行分层,定义每一层之间的接口,每一层通过接口对上层进行提供服务,保证所有的定义与实现分离,这样做,可以保证底层的修改不会影响上一层的运行,
因为已经做到了依赖的最小化。
3、程序模拟
在我们软件的设计过程中,要充分理解和利用接口思想,Martin Fowler[3]在他的《分析模式》一书中指出,分析问题应该站在概念的层次上,而不是站在实现的层次上。所谓的概念层次,就是分析对象该做什么,而不是分析对象怎么做。下面将一个例子来体会。假如有一个老李想加密一个字符串,要求可以根据不同的条件使用不同的方法。在这里,我们使用C#来编写这个需求模拟程序,在VS2005里,新建一个控制台应用程序,
首先引入的要用的命名空间,如下。
using System;
using System.Collections.Generic;
using System.Text;
然后,我们定义一个接口,这个接口规定了要进行加密和解密的通用方法,这里相当于水管和水龙头接触之间的直径大小的规定。
public interface ICryptography
{
string EncryptString(string strNeed2Enc, string key);
string DecryptString(string strNeed2Dec, string key);}
其中方法EncryptString用来进行数据的加密,输入的参数是要进行加密的数据和密钥,返回的是加密之后的数据。方法DecryptString用于数据的解密,参数为要进行解密的数据和密钥。
然后我们编写了两个类,每个类都继承了这个接口,即我们的实现类中都对这个接口中定义的函数进行了实现,对外可以提供相同的方法名和参数。
下面是第一个类FirstCrypt,对这个接口中的方法进行了简单的实现,对传入的参数进行简单的运算,只是在传入的数据和key之间加上了一个“+FirstCrypt+”,并进行了返回。在这里我们称之为加密吧;而另外的解密方法同样就是把这个加密后的值,进行了简单的解密,然后返回。
public class FirstCrypt : ICryptography
{public string EncryptString(string strNeed2Enc, string key)}
{string afterEnc=strNeed2Enc+"+FirstCrypt+"+key;
Console.WriteLine(“FirstCrypt类中的加密方法被调用!”);
return afterEnc;}
public string DecryptString(string strNeed2Dec, string key)
{int pos=strNeed2Dec.IndexOf(“+FirstCrypt+”);
string afterDec=strNeed2Dec.Substring(0,pos);
Console.WriteLine(“FirstCrypt类中的解密方法被调用!”);
return afterDec;}
同样,我们第二个集成了ICryptography接口的类,叫做SecondCrypt,这个类也简单的实现了一个加密和一个解密函数。同时,我们在每个函数中,加入了一个Console类的WriteLine方法的调用,在屏幕上显示现在正在执行的是哪一个语句。
public class SecondCrypt : ICryptography
{public string EncryptString(string strNeed2Enc, string key)}
{string afterEnc=strNeed2Enc+“+SecondCrypt+”+key;
Console.WriteLine(“SecondCrypt类中的加密方法被调用!”);
return afterEnc;}
public string DecryptString(string strNeed2Dec, string key)
{int pos=strNeed2Dec.IndexOf(“+SecondCrypt+”);
string afterDec=strNeed2Dec.Substring(0,pos);
Console.WriteLine(“SecondCrypt类中的解密方法被调用!”);
return afterDec;}

为了模拟老李加解密的需要,同时定义了一个Person类,用其来实例化一个老李,这个类中的一个重要成员,是ICryptography接口类型的m_iCryptObj,在调用的时候,在对这个变量赋值的时候,通过调用CryptObj属性,进行赋值;而Person类,对外提供一个加密和一个解密的方法。
public class Person
{private ICryptography m_iCryptObj;
public ICryptography CryptObj}
get { return m_iCryptObj;}
set {m_iCryptObj=value;}
public Person()
public Person(ICryptography crypt)
{m_iCryptObj = crypt;}
public string WantToCryptString(string str, string key)
{return this.m_iCryptObj.EncryptString(str, key);}
public string WantToDecryptString(string str, string key)
{return this.m_iCryptObj.DecryptString(str, key);}
在Main函数里,首先用类Person实例化一个laoli对象,用FirstCrypt类和SecondCrypt类分别实例化ICryptography 接口类型的firstCrypt对象和secondCrypt对象:
Person laoli = new Person();
ICryptography firstCrypt = new FirstCrypt();
ICryptography secondCrypt = new SecondCrypt();
然后,我们输出一行,标识老李用第一中方法进行加密,接下来很重要的一点是用firstCrypt给laoli的私有成员m_iCryptObj进行赋值,当然是通过CryptObj属性。
Console.WriteLine(“老李想用第一种方式加密:”);
laoli.CryptObj=firstCrypt;
在下面就是调用laoli本身的加解密方法进行加解密,并输出,这个时候调用的是第一种加解密方式:
string need2Enc=“我是老李”;
Console.WriteLine(“要加密的字符串为:”+need2Enc);
string retStr=laoli.WantToCryptString(need2Enc,“OK”);
Console.WriteLine(retStr);
Console.WriteLine(“老李想用第一种方式解密:”);
string beforEnc=laoli.WantToDecryptString(retStr,“OK”);
Console.WriteLine(“解密的字符串为:”+beforEnc);
在第二部分,laoli准备用第二种方式进行加解密,只需要调用laoli.CryptObj=secondCrypt就行了,相关代码如下:
Console.WriteLine(“老李想用第二種方式加密:”);
laoli.CryptObj=secondCrypt;
string need2Enc2=“我是老李”;
Console.WriteLine(“要加密的字符串为:”+need2Enc2);
string retStr2=laoli.WantToCryptString(need2Enc2,“OK”);
Console.WriteLine(retStr2);
Console.WriteLine(“老李想用第二种方式解密:”);
string beforEnc2=laoli.WantToDecryptString(retStr2,“OK”);
Console.WriteLine(“解密的字符串为:”+beforEnc2);
最后的运行结果,如图1:
通过图一,我们可以看出,在接口中声明了一些函数,
那么只要继承了这个接口的类或接口,那么就要实现这个接口中定义的函数。接口的定义唯一,而接口的实现却不唯一。所以,通过一些设计模式,可以达到动态的改变接口的实现,这里面就要用到工厂模式等。面向接口的编程,是面向对象编程思想中重要的一部分,深入理解面向接口的概念和作用,对提高软件的设计能力有很大的帮助。
参考文献:
[1]Bruce Eckel(美),陈昊鹏译,Java编程思想(第4版),机械工业出版社,2007年6月.
[2]程杰著,分析模式:可复用的对象模型,清华大学出版社,2007年12.
[3]Martin Fowler,樊东平张路译,分析模式,机械工业出版社,2004年1月.