計算機學院研二的兄弟與我討論Java
一見面
幾個問題全是關於接口
接口有什麼用?為什麼要用接口?什麼時候該使用接口?很慶幸他們不是問我Java如何連接SQL Server
或者是如何開發J
EE應用
這類問題有殺傷力
避之則吉
今年計算機學院本科有個畢業設計課題是做J
ME
選這個題目的學生在
月末都還在苦著臉研究java
util
*這個包
這個這個……唉
大多數人認為
接口的意義在於頂替多重繼承
眾所周知Java沒有c++那樣多重繼承的機制
但是卻能夠實作多個接口
其實這樣做是很牽強的
接口和繼承是完全不同的東西
接口沒有能力代替多重繼承
也沒有這個義務
接口的作用
一言以蔽之
就是標志類的類別(type of class)
把不同類型的類歸於不同的接口
可以更好的管理他們
OO的精髓
我以為
是對對象的抽象
最能體現這一點的就是接口
為什麼我們討論設計模式都只針對具備了抽象能力的語言(比如c++
java
c#等)
就是因為設計模式所研究的
實際上就是如何合理的去抽象
(cowboy的名言是
抽象就是抽去像的部分
看似調侃
實乃至理)
設計模式中最基礎的是工廠模式(Factory)
在我最近的一個很簡單的應用中
我想盡量的讓我的程序能夠在多個數據庫間移植
當然
這涉及很多問題
單是如何兼容不同DBMS的SQL就讓人頭痛
我們不妨先把問題簡單化
只考慮如何連接不同的數據庫
假設我有很多個類
分別是Mysql
java
SQLServer
java
Oracle
java
DB
java
他們分別連接不同的數據庫
統一返回一個Connection對象
並且都有一個close方法
用於關閉連接
只需要針對你的DBMS
選擇不同的類
就可以用了
但是我的用戶他會使用什麼數據庫?我不知道
我希望的是盡量少的修改代碼
就能滿足他的需要
我可以抽象如下接口
package org
bromon
test;
public interface DB
{
java
sql
Connection openDB(String url
String user
String password);
void close();
}
這個接口只定義兩個方法
沒有任何有實際意義的代碼
具體的代碼由實作這個接口的類來給出
比如Mysql
java
Package org
bromon
test;
import java
sql
*;
public class Mysql implements DB
{
private String url=
jdbc:mysql:localhost:
/test
;
private String user=
root
;
private String password=
;
private Connection conn;
public Connection openDB(url
user
password)
{
//連接數據庫的代碼
}
public void close()
{
//關閉數據庫
}
}
類似的當然還有Oracle
java等等
接口DB給這些類歸了個類
在應用程序中我們這樣定義對象
org
bromon
test
DB myDB;
使用myDB來操作數據庫
就可以不用管實際上我所使用的是哪個類
這就是所謂的
開
閉
原則
但是問題在於接口是不能實例化的
myDB=new DB()
這樣的代碼是絕對錯誤的
我們只能myDB=new Mysql()或者myDB=new Oracle()
麻煩了
我還是需要指定具體實例化的是哪個類
用了接口跟沒用一樣
所以我們需要一個工廠
package org
bromon
test;
public class DBFactory
{
public static DB Connection getConn()
{
Return(new Mysql());
}
}
所以實例化的代碼變成
myDB=DBFactory
getConn()
這就是
種模式中最基礎的普通工廠(Factory)
工廠類負責具體實例化哪個類
而其他的程序邏輯都是針對DB這個接口進行操作
這就是
針對接口編程
責任都被推卸給工廠類了
當然你也可以繼續定義工廠接口
繼續把責任上拋
這就演變成抽象工廠(Abstract Factory)
整個過程中接口不負責任何具體操作
其他的程序要連接數據庫的話
只需要構造一個DB對象就OK
而不管工廠類如何變化
這就是接口的意義
抽象
繼承的概念不用多說
很好理解
為什麼要繼承呢?因為你想重用代碼?這絕對不是理由
繼承的意義也在於抽象
而不是代碼重用
如果對象A有一個run()方法
對象B也想有這個方法
所以有人就Class B extends A
這是不經大腦的做法
如果在B中實例化一個A
調用A的Run()方法
是不是可以達到同樣的目的?如下
Class B
{
A a=new A();
a
run();
}
這就是利用類的聚合來重用代碼
是委派模式的雛形
是GoF一貫倡導的做法
那麼繼承的意義何在?其實這是歷史原因造成的
最開始的OO語言只有繼承
沒有接口
所以只能以繼承來實現抽象
請一定注意
繼承的本意在於抽象
而非代碼重用(雖然繼承也有這個作用)
這是很多Java爛書最嚴重的錯誤之一
它們所造成的陰影
我至今還沒有完全擺脫
壞書害人啊
尤其是入門類的
流毒太大
什麼時候應該使用繼承?只在抽象類中使用
其他情況下盡量不使用
抽象類也是不能實例化的
它僅僅提供一個模版而已
這就很能說明問題
軟件開發的萬惡之源
一是重復代碼而不是重用代碼
二是爛用繼承
尤以c++程序員為甚
Java中取締多重繼承
目的就是制止爛用繼承
實是非常明智的做法
不過很多人都不理解
Java能夠更好的體現設計
這是讓我入迷的原因之一
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19330.html