继承"基类"跟继承"接口"都能实现某些相同的功能,但有些接口能够完成的功能是只用基类无法实现的
1.接口用于描述一组类的公共方法/公共属性. 它不实现任何的方法或属性,只是告诉继承它的类
《至少》要实现哪些功能,继承它的类可以增加自己的方法.
2.使用接口可以使继承它的类: 命名统一/规范,易于维护.比如: 两个类 "狗"和"猫",如果它
们都继承了接口"动物",其中动物里面有个方法Behavior(),那么狗和猫必须得实现Behavior()方法,
并且都命名为Behavior这样就不会出现命名太杂乱的现象.如果命名不是Behavior(),接口会约束
即不按接口约束命名编译不会通过.
3.提供永远的接口。 当类增加时,现有接口方法能够满足继承类中的大多数方法,没必要
重新给新类设计一组方法,也节省了代码,提高了开发效率.
举个代码示例:
//公共接口: "动物"
public Interface IAnimal
{
int EyeNumber;
private void Behavior(); //行为方法,描述各种动物的特性
}
//类: 狗
public Dog : IAnimal
{
string ActiveTime = "白天";
private void Behavior()
{
Console.Write("我晚上睡觉,白天活动");
}
}
//类: 猫
public Cat: IAnimal
{
string ActiveTime = "夜晚";
private void Behavior()
{
Console.Write("我白天睡觉,晚上活动");
}
}
//简单的应用:
public static Main()
{
Dog myDog = new Dog();
myDog.Behavior(); //输出: "我晚上睡觉,白天活动"
Cat myCat = new Cat();
myCat.Behavior(); //输出: "我白天睡觉,晚上活动"
}
以上调用不同的类的相同名方法,会输出不同的东东,也就是说每个类里面的同名方法完成的
功能可以是完全不同的.
更进一步,不是用上面Main方法这样一个一个调用类的方法,用多态性实现其调用.
看一下下面这个方法:
public Behavior(IAnimal myIanimal)
{
myIanimal.Behavior();
}
其参数是<<接口类型>>,任何继承它的类都可以调用此方法,此方法能根据类的不同调用不同的类
中的方法. 也即能够自己根据不同的类,完成不同的类的功能.
多态性代码示例:
Dog myDog = new Dog();
Cat myCat = new Cat();
Behavior(myDog); //Behavior接受“狗”类实例
Behavior(myCat); //Behavior接受“狗”类实例
这样Behavior方法写一次就能完成所有继承它的类中的相同名方法的不同功能. 非常方便,
同样,由于“动物软件”功能需求,需要再增加一个"龟"类:
//类: 龟
public Tortoise: IAnimal
{
string ActiveTime = "很难说";
private void Behavior()
{
Console.Write("我可以不活动,一睡就睡五千年!");
}
}
那么也可以调用上面多态方法,所以说接口使方法具有较好扩展性.
如果继承它的类很多的话,有多少好处是可想而知的!
----------------------------------------------------------------------------------------------------------------------------------------
<script src="../../../163new.js" type="text/javascript"></script>
<script type="text/javascript">
</script> <script src="../../../../pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> | |
[返回首页] - [索引页面] - [文章列表]
主题:针对接口编程,我始终有点领悟不透
也许是我太笨了,有个问题我始终不能理解。我举个例子来说明吧,比如我要写一组连接数据库的类,其中SQLServer.java负责连接MS SQLServer数据库;PostGres.java负责连接PostGreSQL数据库。那么我定义一个接口:
public interface ConnDB { public Connection getConn(String url,String user,String pwd); public void close(); }
用户在连接数据库的时候针对接口编程: ConnDB myDB=new SQLServer(); 或者 ConnDB myDB=new PostGres();
但是用户仍然需要指明它实例化的是哪个类啊,虽然产生的myDB是ConnDB类型的,但是最终还是要指出实际实例化的是谁。如果要更换数据库的化,他还是需要修改代码啊?这样一来针对抽象编程的意义何在呢?开闭原则是如何体现的呢?
我笨了一点,大家不要说我,希望指点,非常感谢。
回复人:sean_gao(大胃) 一星(中级) 信誉:105 2004-5-10 1:47:19 得分:5
|
| 接口统一了,实现可以千差万别,我们都可以按相同的方式访问。拿JDBC来说,很多东西都是接口,实际上就像是个架子,各个不同的数据库厂商或者第三方根据这个框架往里面塞具体的驱动实现,对于JDBC的使用者而言,这些都不必关心,按着JDBC的统一方式访问数据库就可以了,很多时候这样做也带来代码重用的方便,对不同的数据库,只需要修改少量参数而不必修改具体访问细节,而这一步也很容易放到具体程序之外,从而使代码尽可能的独立于具体的数据库,这对于程序的维护是很有好处的。
对于用户是不是真的需要知道具体类,我想: 1、就算真的需要知道具体的类,在类的对象产生后还有一个如何操纵对象的问题,假如程序中需要的具体对象所属的类不一样,但接口一致的话,那么我们很容易以利用多态写出更简洁且容易扩展的代码。 2、很多时候对象的最终的使用者和类/对象的构造者并不是同一个人,他们之间还需要一个抽象层作为contract,这个时候接口的作用还是很明显,就像前边提到的JDBC。
随便说说,可能有片面的地方,甚至也可能存在理解偏差和不足,欢迎批评指正。
| TOP |
回复人:masakiyy(我的老婆是岚岚) 二级(初级) 信誉:100 2004-5-10 7:41:06 得分:0
|
| 呵呵,如果是我,我会用abstract class做
| TOP |
回复人:yeshucheng(叶澍成) 五级(中级) 信誉:100 2004-5-10 8:33:12 得分:0
|
| 在我看来,象楼主很有针对性,确实到不如用抽象类或许是种更好的方式
| TOP |
回复人:bromon(我的媳妇是....) 五级(中级) 信誉:100 2004-5-10 10:15:26 得分:0
|
| 那么在这个例子中,应该如何体现用户不需要修改原有程序,就可以在连接不同dbms的类之间转换呢?
| TOP |
回复人:baichuan168(百川) 二级(初级) 信誉:100 2004-5-10 10:35:57 得分:0
|
| 先写一个工程类 public DBFactory() {
}
| TOP |
回复人:baichuan168(百川) 二级(初级) 信誉:100 2004-5-10 12:08:36 得分:0
|
| sorry,刚才不小心提交了 public DBFactory() { public IConnDB builderDB(string DBType) { if(DBType.equals("SQLServer") return SQLDB; if(DBType.equals("MYSQL") return MYSSQLDB ..... }
} 当然,MYSSQLDB和SQLDB都要实现IConnDB
| TOP |
回复人:yuzhouheng(jacky) 二级(初级) 信誉:100 2004-5-10 12:58:20 得分:0
|
回复人:fohoo(飞狐) 三级(初级) 信誉:100 2004-5-10 15:41:52 得分:5
|
| 同意baichuan168(百川),使用factory模式返回接口
我建议使用static方法更好些,用Class.forName能灵活,方便增加数据库的支持而无需改代码
**测试代码中,我把getConn返回值改成了String,实际用Connection
public class test1 { public static void main(String[] args) throws Exception{
IConnDB connPostgres = DBFactory.getConnDB("PostgresSQLConn"); connPostgres.getConn("","",""); connPostgres.close(); IConnDB connMYSQL = DBFactory.getConnDB("MYSQLConn"); connMYSQL.getConn("","",""); connMYSQL.close(); } }
interface IConnDB{ public String getConn(String url,String user,String pwd); public void close(); }
class DBFactory{
static public IConnDB getConnDB(String DBType) throws Exception { return (IConnDB)Class.forName(DBType).newInstance(); }
}
class PostgresSQLConn implements IConnDB{
public String getConn(String url, String user, String pwd) { System.out.println("call PostgresSQLSQL.getConn"); return null; }
public void close() { System.out.println("call PostgresSQLSQL.close");
} }
class MYSQLConn implements IConnDB{ public String getConn(String url, String user, String pwd) { System.out.println("call MYSQLConn.getConn"); return null; }
public void close() { System.out.println("call MYSQLConn.close"); } }
| TOP |
回复人:qljsd(我本善良) 五级(中级) 信誉:99 2004-5-10 15:48:35 得分:5
|
| 我觉得应该这样来理解。 如果你自己做一个系统,什么都订好了,什么都是你自己写,你根本不需要接口和抽象类。 但如果不是这样,接口和抽象类就相当有用了。接口定义了一个标准,实现这个标准可以有不同的方式。比如你说的,你换了一个数据库,你是需要写那个数据库的实现代码,但对于调用getConn(String url,String user,String pwd)方法的客户不必做任何的改动,因为你是按标准调用的。你对开闭原则理解也有误,你想增加新的功能而不加(改)代码是不可能(难道你能写出万能的代码?!)。开闭原则简单的说就是,当你对系统有新功能加入时,对原有代码尽量少改动或不改动(就是不要改已经写好的类,增加新的类)。当然我这样说有点不全面,但是这样你好理解点。其他的以后慢慢体会吧。
| TOP |
回复人:vcshcn(黑天的猩猩) 三级(初级) 信誉:100 2004-5-10 16:01:06 得分:0
|
| 我觉得好处就是把功能和实现相分离,容易修改和扩展
| TOP |
回复人:bromon(我的媳妇是....) 五级(中级) 信誉:100 2004-5-10 17:12:25 得分:0
|
| 如果按照这段工厂代码: public IConnDB builderDB(string DBType) { if(DBType.equals("SQLServer") return SQLDB; if(DBType.equals("MYSQL") return MYSSQLDB ..... }
那么用户同样需要在使用工厂的时候指定参数DBType是"SQLServer"或者是"MYSQL",同样需要更改代码、重新编译才能更换数据库,对不对?这怎么能体现开闭原则呢?
| TOP |
回复人:Tetra(Tetra) 一级(初级) 信誉:99 2004-5-10 17:21:48 得分:0
|
| 用reflect或者class.forName,从一个配置文件中初始化不就可以不重新编译来更改数据库了
| TOP |
回复人:bromon(我的媳妇是....) 五级(中级) 信誉:100 2004-5-10 17:37:52 得分:0
|
| 如果要使用配置文件的话,何以再用接口和工厂呢?
在配置文件中写明驱动程序名称、URL、帐号、密码,换数据库只要改配置文件就可以了,何必再使用接口和工厂呢?不能为了用而用吧?
| TOP |
回复人:frean(天颖) 二级(初级) 信誉:105 2004-5-10 23:18:15 得分:5
|
| 1、在配置文件中配置数据源。 2、利用抽象工厂模式,根据数据源的种类创建多个相应的具体工厂,在这些具体工厂中根据数据源配置实现Connection。 3、定义抽象产品接口,如UserDAO interface等。 4、实现具体产品,如MySQLUserDAO class、OracleUserDAO class等。 5、在相应的具体工厂中返回抽象产品接口,如MysqlFactory class中有一个方法,getUserDAO() {return new MySQLUserDAO();}等等 6、当需要利用什么样的数据源的时候就调用什么工厂,就可以实现一个系统多个数据库存储方式了。 7、当系统发布后,可以随便客制化系统的数据库。 利用这个实现方式,应该明白接口和抽象类的好处了吧,愿意与大家多交流,有意者可以给我留言。
| TOP |
回复人:raimundo(沉默的大多数) 三级(初级) 信誉:100 2004-5-11 16:02:58 得分:50
|
| 赫赫。这是一般都会有的迷惑,书上说用要针对interface编成,减少对具体实现的依赖,但是往往书上都不说具体怎么体现出易于修改的优越性。 使用interface最重要的思想就是分离关注点,既然是分离,就一定要有组装的机制,搂主可以参考以下的方式组装组件: 1.Dependency Injector Container,如Pico,Spring 2.Factory Method,Abstract Factory,Builder等Pattern
| TOP |
回复人:bromon(我的媳妇是....) 五级(中级) 信誉:100 2004-5-11 23:17:54 得分:0
|
| 楼上的算是说到我心里去了,能不能讲得详细点?或者推荐点资料看?
| TOP |
回复人:BestSky(天空) 一级(初级) 信誉:100 2004-5-12 0:28:49 得分:0
|
| 迷惑中,一直看接口编程,没法现到底怎么回事,水能给出个实例>对比接口非接口的优劣?
| TOP |
回复人:raimundo(沉默的大多数) 三级(初级) 信誉:100 2004-5-12 10:41:07 得分:0
|
| 赫赫,举个例子吧,简单的排序
interface ISortStrategy { Collection sort(Collection c); }
这个接口定义了一个排序算法,也就是对接口的给出了语义上的定义(即实现该接口的必须是一种排序算法),而没有给出接口实现上的限定,所以有可能:
BubbleSortStrategy implements ISortStrategy { ..... } 或 QuickSortStrategy implements ISortStrategy { } 等
那么在具体应用的时候可能是
public void method(ISortStrategy sortStatrgy) { .... c = sortStatrgy.sort(c); .... } 比起 public void method() { .... 具体的算法 .... }
对于方法method而言,第一个是易于修改的,使用interface提高了扩展性,符合开闭原则之类的 but it'is not the whole story,我想楼主的问题是谁负责把具体的ISortStrategy传给method?这一部分代码怎么体现开闭原则之类的问题? 重要的一点也是容易忽略的一点就是针对interface编程带来的易修改性是有scope的,比如 class A { void method(ISortStrategy sortStatrgy) { ..... } pubic void main(String[] args) { A a = new A(); a.method(new BubbleStoreStrategy()); } } method是针对接口编成的,所以interface的优越性只限于method这个方法的scope之内,而不包含class A,main方法不是按照接口编成,而是提供具体的实现类,所以具体算法变更的时候还是要修改main方法源代码的。所以我们说开闭原则只是这对这个类中的method方法符合开闭原则,而对于其他方法或者这个类本身并不符合!!! 那么怎么怎样衡量一个class的设计是符合开闭原则的,是按接口编成的呢?就是这个class的所有method都是开闭的,都是按interface的设计,这种设计的内在哲学就是把和具体实现类的耦合关系转交给其他类而已,也就是让别的类不符合开闭原则,而自己符合开闭原则,往好了说是明哲保身,往怀了说点损人利己的意思:) Design Pattern中创建模式有很多这样权衡的例子,比如Factory pattern class Application { main() { Application app = ApplicationAssembler.getInstance().assemble(); } } 我们可以说这个Application是满足开闭的,修改装配方法不用修改这个类,我们是通过使用Factory Pattern把构造时候对具体类的耦合转交给Factory类(也就是ApplicationAssembler),而使程序本身易于维护,使用一个处于次要地位的类不满足开闭原则而使系统主要部分易于扩展,这就是Pattern的,权衡后的中庸。
| TOP |
回复人:raimundo(沉默的大多数) 三级(初级) 信誉:100 2004-5-12 10:50:04 得分:0
|
| 还有一些技巧可以让修改脱离code的层次,而改为纯文本的修改,比如: class XXXFactory { public XXX create() { 从一个XML中读取数据,声称XXX } } 再比如 class XXXFactory { public XXX create() { 从一个纯文本中读取脚本,执行脚本声称XXX } } 这个类也是开闭的,因为修改的时候不用修改代码,而是去修改配置文件或是配置脚本 目前流行的做法是使用Pico,Spring这类的Dependency Injector Container,虽然原理上也是把修改外化为纯文本,但是由于Dependency Injector的强大思想可以督促我们开发出针对interface编成的类,因此这类轻量容器从去年起就非常的流行,楼主可以参考www.picocontainer.org,www.springframeworks.org,Martin Flower的一篇文章DIP,Apache Avalon Framework,XWork等
| TOP |
回复人:bromon(我的媳妇是....) 五级(中级) 信誉:100 2004-5-12 13:34:26 得分:0
|
| raimundo()
非常感谢你,你的回复让我明白了很多东西。谢谢
| TOP |
回复人:javadanny(开始郁闷了) 一级(初级) 信誉:100 2004-5-12 13:42:55 得分:0
|
| 是啊。像组装电脑一样,只要接口相同都可以装组起来啊 增加软件的可扩充性,独立性,可维护性。
| TOP |
回复人:Eri(阳光下的阴影) 一级(初级) 信誉:100 2004-5-12 14:29:37 得分:0
|
回复人:guyuanwuxin() 一级(初级) 信誉:102 2004-5-12 14:49:44 得分:0
|
| 针对接口编写程序就是针对抽象编写程序 这是面向对象的基本原则立场 至于你是用什么模式就是你自己的问题了.
| TOP |
回复人:superryu(龙) 二级(初级) 信誉:100 2004-5-12 16:09:07 得分:0
|
回复人:chinajust(一天) 二级(初级) 信誉:100 2004-6-9 22:16:47 得分:10
|
| 共同讨论; 首先,接口在java是解决多个继承的问题,所以接口应该偏重共性的东西,比如你上面所说的数据实现方式,你可以定义一个mssql 和其他数据库公用的方法如 你上面所写的
public interface ConnDB { public Connection getConn(String url,String user,String pwd); public void close(); }
然后,用工厂模式 public static class DBFactory{ public ConnDB static getDBInstance(int dbType){
switch(dbType){ case 1: return new MSSqlDB(); case 2; return new OtherDB(); default: return null; }
} }
最后在程序中调用, ConnDB gg=DBFactory.getInstance(1); gg.getConnection(...); ,,
| TOP |
回复人:wdong18(东东) 四级(中级) 信誉:105 2004-6-9 23:54:24 得分:0
|
| 从 ConnDB myDB=new SQLServer(); 到 ConnDB myDB=new PostGres(); 退一步想,如果要修改,只改这一行就可以了。工程其他SRC不受影响。 从 SQLServer myDB=new SQLServer(); 到 PostGres myDB=new PostGres(); 工程受到的影响就很大了。工程中所有使用myDB的位置,估计都需要改变。
| TOP |
回复人:glchengang(青面) 一级(初级) 信誉:100 2004-6-11 18:04:13 得分:0
|
| http://blog.beok.net/more.asp?name=glchengang&id=97
这篇文章完全就是为你写的,在文章最后提到,你只需要在一个文本文件里改个值,你的就可以支持不同的数据库了,这就是开闭原则的体现
| TOP |
回复人:bjshasha(傻傻) 一级(初级) 信誉:100 2004-6-11 21:01:17 得分:0
|
回复人:hailong326(望尘莫及) 二级(初级) 信誉:86 2004-6-12 17:05:11 得分:0
|
回复人:programer23(亮子) 四级(中级) 信誉:100 2004-6-13 17:51:12 得分:0
|
| 楼上说的都不错,但我认为你不应该硬记代码例子,你应该记主实际例子,在活学活用! 如:接口你理解成角色,如:扮演皇帝的角色。演员演了这个角色就实现了它! 如果你针对一个演员来操作的话,你是很受约束的,如果你对皇帝这个角色来操作呢,你就有很大的余地!说白了就是“不行换演员呗”!这是核心,希望 你懂了!
| TOP |
回复人:Sptan(学不会C++) 一级(初级) 信誉:100 2004-6-15 9:55:46 得分:0
|
| 根据我的理解,针对接口编程不是为了不修改代码,而是尽量把代码修改减到最少,最好为一次修改就满足需求变化。 针对你自己提出的例子,用户是要指定要实例化的类,可是以后的调用就不必再和这个实例类相挂钩了(当然是指在代码上,不是实际的运行).如果以后用户想改变实现,只要在实例化类的那个地方修改就行了,其他地方的代码是不需要改动的. 我只是针对你提出的问题来就事论事,说明接口的一个好处,当然不全面,再说我也不是面向对象高手,说的有纰漏,希望大家为我改正,谢了先.
| TOP |
回复人:truezerg(赵明宇) 四级(中级) 信誉:105 2004-6-17 14:43:30 得分:0
|
| 你非得在程序中显示的创建一个具体的类吗? 用一个工厂来创建,用配置文件来配置你到底想创建哪个具体类,到时候要换数据库的时候,改一下配置文件的配置就完事了。什么代码都不用改。
在这个问题上,楼主问的问题其实和为什么用接口无关,用接口的目的在这里是可以随意的“更换”实现,楼主主要的问题是不知道如何“更换”而矣
| TOP |
回复人:0flying0(j2ee的狂热分子) 三级(初级) 信誉:100 2004-6-17 16:27:13 得分:0
|
回复人:liudongbaollz() 一级(初级) 信誉:100 2004-6-17 22:12:09 得分:10
|
| 我是这么理解的:所谓接口其主要的思想应该是一种约定,也可以说是一种合同,主要目的是用于Client 和 Server 的交互,通常Client 使用Server 提供的接口,Client 只需知道Server提供哪些服务(由接口的各个方法集合体现),具体服务是如何实现的Client不需关心,也不能让他知道,对于你说的这种情况用不用接口都无所谓,可以实现一个ConnDBFactory(最好采用唯一模式创建一个唯一的类工厂) { SQLServer CreateSQLServer(...); PostGres CreatePostGres(...); } 用户(即Client)根据需要调用相应的创建方法。
{ 但是用户仍然需要指明它实例化的是哪个类啊,虽然产生的myDB是ConnDB类型的,但是最终还是要指出实际实例化的是谁。如果要更换数据库的化,他还是需要修改代码啊?这样一来针对抽象编程的意义何在呢?开闭原则是如何体现的呢?}
无论任何时候,用户也必须承担一定的责任,类似合同的双方互有责任和义务一样,接口也并不是说由Server承担所有的责任!神都不是万能的!
| TOP |
回复人:XKes() 一级(初级) 信誉:100 2004-6-22 17:06:37 得分:0
|
| 耦合度能降到什么程度。 具体问题具体分析了…… 不必太拘泥了…… 从前好多人说我是学院派的,到现在还耿耿于怀:)。
| TOP |
回复人:alienbat(亡灵法师) 五级(中级) 信誉:105 2004-6-23 0:13:53 得分:0
|
回复人:huzengli(网际过客) 二级(初级) 信誉:95 2004-7-10 23:09:22 得分:0
|
| 使用的接口的好处是可以降低系统的耦合,具体说调用接口者不需要关心接口的实现,调用者的程序 只会依赖接口的定义,而不用依赖接口的实现。
| TOP |
回复人:taciya(taciya) 一级(初级) 信誉:66 2004-7-11 9:56:32 得分:0
|
| 在这里,我只针对针对接口编程的好处说明一下。。 还是用的你例子来说: 针对接口其中优点之一就是可以让客户端黑箱操作,不管ConnDB的实例是什么,都是用 同样的方式对待它。就是让客户端与实例尽可能拖耦,尤其当客户端以来于这个ConnDB 例如 public class client{ public void op(ConnDB con) } 这样,不管传入的实例是什么,客户端都不用做改动,这样就将偶合度最大限度的降低了。 至于服务器端如何实现,客户不关心。 这样只要接口一致客户代码和服务代码可以并行开发,提高效率。
| TOP |
回复人:cocolovevienna(狂徒再世) 四级(中级) 信誉:94 2004-7-11 20:57:21 得分:0
|
| 对,精练。接口类能存贮任何实现这个接口的类的实例。
| TOP |
回复人:Aiolosz(浮一大白) 一级(初级) 信誉:100 2004-7-12 11:31:25 得分:0
|
| 看来这里大家的学习气氛挺好的啊,我也来学一点,莫笑啊,
| TOP |
回复人:hykwolf(Yankang Hu) 五级(中级) 信誉:100 2004-7-12 11:53:05 得分:0
|
| //综合class.forName()和工厂的方法 修改factory方法,这样你无需修改程序了,只需要知道连接用的bean的name就好了 public static IConnDB getInstance(string DBclass) { IConnDB conn = Class.forName(DBclass).newInstance(); return conn; }
| TOP |
回复人:hykwolf(Yankang Hu) 五级(中级) 信誉:100 2004-7-12 12:06:23 得分:10
|
| sorry,没写完 但是这样也有一个局限,当你很多文件调用了getInstance("aaa")的方法后 某一天,aaa.class需要被替换为aab.class,这时候,致命的东西来了,需要更新所有的 getInstance("aaa")方法或者修改aab.class,但假若aaa.class有必须保存,那么这是致命的修改 所以就算是定义了工厂,同样需要在调用工厂的程序中指定唯一的参数,这就隐含了一个缺陷 显然这样将配置参数分散到每一个程序中部是一个好的方法,如果我们可以把这些配置参数集中起来 即getInstance("aaa");只出现一次,而不是很多次,这是后我们就比较好修改了
这个利用raimundo()说的外部文件的方法,把损人不利己的东西交由一个外部配置文件完成 这样所有的参数集中在了一个xml or txt文件上,而参数到程序的关键集中在了这个文件的解析上 这样可以把不开闭的集中在2个东西上,一个是配置文件,一个是解析程序.
| TOP |
回复人:naomaomao(孬毛毛) 四级(中级) 信誉:98 2004-7-12 16:24:26 得分:0
|
| 收益非浅~~~~:)看了上面的各位讲解,好象针对接口编程,跟工厂模式、反射机制,联系的都很紧密哦~~不知道能不能抛弃工厂模式、多继承,在其他方面再深入谈一下针对接口编程的好处呢~~~
| TOP |
回复人:hykwolf(Yankang Hu) 五级(中级) 信誉:100 2004-7-12 16:50:42 得分:0
|
| 2各开发组,a开发数据库连接bean,b使用连接bean开发 在它们之间需要一个什么衔接呢?就是接口 a,b制定了一个接口(这也可能只是一个准则),而接口定义了标准的使用方法. 开发中,b按照接口使用,而a呢,他们遵循接口开发隐藏于接口后的东西,两者的版本将不受任何一方的限制,而双方又都不知道对方如何开发,他们只知道一个对应接口开发,一各按照接口开发,各司其职,各谋其政,互不影响,互不干涉.
如果没有了那么接口,会发生什么? 1. a男:b男今天我加了一个方法,很好用的哦,效率提高200%,来我的ftp下在更新的版本 b男:x死这小丫的,老子又要改那xx个文件了,看我怎么整你 翌日 b男:小a啊,才想起来,我需要一个这个功能,明天就要哈哈,这里是经理签字的公单,收好了阿 a男:##$&&<>FFF123
翌翌日 经理:你们2个混蛋......(粗话略)
翌翌翌日 罗马竞技场: "小b,你个xx男,看我则么k死你" "xa,你个x片的!@#%$$^" 观众席:"今天的决斗一定非常精彩"
| TOP |
回复人:qiujoe(迷糊) 一级(初级) 信誉:100 2004-7-12 17:17:10 得分:0
|
| 但是用户仍然需要指明它实例化的是哪个类啊,虽然产生的myDB是ConnDB类型的,但是最终还是要指出实际实例化的是谁。如果要更换数据库的化,他还是需要修改代码啊?这样一来针对抽象编程的意义何在呢?开闭原则是如何体现的呢? ===========================================================
你有此疑问的原因在于,你的经验不够,
| TOP |
回复人:qhgary(Shining) 三级(初级) 信誉:106 2004-7-22 16:00:29 得分:0
|
| 你说得很对,但是如果你采用上面说的Factory模式,把需要实例化的类以参数的形式带入,那么这个问题就解决了,当然你会说,那这个参数还是在代码里面阿,那我要改的时候还是要改代码阿,没错。那你就不能把这个参数放到一个文件里面么,运行的时候动态的读出这个参数,以后修改的时候只要更换这个text文件里面的就可以了,这个text文件可以用xml来做。
| TOP |
回复人:tyrone98(林林) 二级(初级) 信誉:100 2004-7-25 10:56:42 得分:0
|
| 你对接口的理解不够。就拿JDBC来说吧,你想做一个程序对任何数据库都能访问。不同的数据库的查询实现肯定是不一样的,JDBC就提出以下几个常用接口: 1.Connection 2.Statement 3.ResultSet ... 等接口: Connection 可以新建Statement , Statement的执行可以返回ResultSet,ResultSet返回的结果可以进行查阅。如果没有JDBC的接口,那么多数据库写出来的类库肯定是五花八门。有了接口,你可以从DriverManager得到一个Connection ,然后你的程序写完了,只要在DriverManager中取得不同的数据库连接,另外的程序就不用改了。 单单看一个接口可能不明白接口的作用,其实你可以把一组接口看成是一个空框架,它没有任何的代码实现。
| TOP |
回复人:bromon(我的媳妇是....) 五级(中级) 信誉:100 2004-7-25 16:46:31 得分:0
|
| 谢谢大家的回复,让我学到了很多,现在再看java与模式,有豁然开朗的感觉,爽。
大家的回复我会整理一下,放到我的blog上供人参考。楼上诸位如果有谁觉得这样做侵犯您的权益,请提出来,您的回复将不会出现在我的blog中。
还希望有更多的人参与讨论,所以暂时不打算结帖,请大家理解。
| TOP |
回复人:cocolovevienna(狂徒再世) 四级(中级) 信誉:94 2004-7-25 21:44:21 得分:0
|
| 我现在真的有点明白创建型模式的真正含义了。不再是书上的那几个UML图了。
| TOP |
回复人:liqj2ee(强子) 一级(初级) 信誉:100 2004-7-26 13:30:55 得分:0
|
| 这个接口会被继承SQLServer有他的ConnD BostGreSQL也有他的ConnD,但是由于他们都继承自ConnD,所以可以用这个接口表示
| TOP |
回复人:imagex(<<<<<<★>>>>>>) 二级(初级) 信誉:88 2004-7-28 13:52:25 得分:0
|
| public class test1 { public static void main(String[] args) throws Exception{
IConnDB connPostgres = DBFactory.getConnDB("PostgresSQLConn"); connPostgres.getConn("","",""); connPostgres.close(); IConnDB connMYSQL = DBFactory.getConnDB("MYSQLConn"); connMYSQL.getConn("","",""); connMYSQL.close(); } }
interface IConnDB{ public String getConn(String url,String user,String pwd); public void close(); }
class DBFactory{
static public IConnDB getConnDB(String DBType) throws Exception { return (IConnDB)Class.forName(DBType).newInstance(); }
}
class PostgresSQLConn implements IConnDB{
public String getConn(String url, String user, String pwd) { System.out.println("call PostgresSQLSQL.getConn"); return null; }
public void close() { System.out.println("call PostgresSQLSQL.close");
} }
class MYSQLConn implements IConnDB{ public String getConn(String url, String user, String pwd) { System.out.println("call MYSQLConn.getConn"); return null; }
public void close() { System.out.println("call MYSQLConn.close"); } }
| TOP |
该问题已经结贴 ,得分记录:sean_gao(5)、fohoo(5)、qljsd(5)、frean(5)、raimundo(50)、chinajust(10)、liudongbaollz(10)、hykwolf(10)、
<script language="javascript" src="../../../bottom.js" type="text/javascript"></script> | |