Java程序設計中的接口應用
發(fā)表時間:2024-01-11 來源:明輝站整理相關軟件相關文章人氣:
[摘要]Java語言提供了一種接口(interface)機制。這種接口機制使Java的面向?qū)ο缶幊套兊酶屿`活。我們可以用接口來定義一個類的表現(xiàn)形式,但接口不能包含任何實現(xiàn)。在《Thinking in Java》一書中,作者對接口有這樣的描述:“接口(interface)比抽象(abstract)的概念更...
Java語言提供了一種接口(interface)機制。這種接口機制使Java的面向?qū)ο缶幊套兊酶屿`活。我們可以用接口來定義一個類的表現(xiàn)形式,但接口不能包含任何實現(xiàn)。在《Thinking in Java》一書中,作者對接口有這樣的描述:“接口(interface)比抽象(abstract)的概念更進了一步。你可以把一個接口看成是一個純的抽象類!蔽艺J為作者對接口的這一解釋再準確不過了。
理解并用好接口機制將幫助我們更好的掌握Java這種面向?qū)ο蟮木幊陶Z言。下面我們來討論一下接口的使用規(guī)則以及相關的應用。
一、接口的定義及實現(xiàn)
定義接口和定義類相似,只是要把 class關鍵字換為 interface。定義方法時只需要方法名,返回類型和參數(shù)列表,不能有方法體。接口中可以定義字段,這些字段都被暗指為 static 和 final,因此應該根據(jù)需要先定好這些字段的值。例如:
public interface Flyable {
void fly();
}
public interface Talkable {
void talk();
}
public interface Message {
int MAX_SIZE = 4096;
String getMessage();
}
上面定義的幾個接口中,F(xiàn)lyable 和 Talkable 只定義了一個方法,而 Message 里除了方法外還有一個字段 MAX_SIZE?梢钥闯鲞@些接口只定義了類的表現(xiàn)形式,而不包含任何實現(xiàn),所以不能直接使用。要使用這些接口就需要有相應的類去實現(xiàn)它們。實現(xiàn)接口時應該先在類名后用 implements 關鍵字申明將要實現(xiàn)的接口,如果要實現(xiàn)多個接口,應該用逗號將它們隔開,然后一一實現(xiàn)這些接口中定義的方法。如下面的例子:
public class Parrot implements Flyable, Talkable {
public void fly() {
System.out.println("Flying like a parrot…");
}
public void talk() {
System.out.println("Hello! I am a parrot!");
}
}
public class TextMessage implements Message {
String message;
public void setMessage(String msg) {
message = msg;
if (message.length() > MAX_SIZE)
message = message.substring(0, MAX_SIZE);
}
public String getMessage() {
return message;
}
}
在 Parrot(鸚鵡)例子中,我們用接口 Flyable 來表示飛行能力,Talkable 表示說話能力,但它們并不包含具體實現(xiàn)。而 Parrot 同時具有這兩種能力,所以我們?yōu)?Parrot 類同時實現(xiàn)了 Flyable 和 Talkable 這兩個接口。同樣我們還可以定義一個Swallow(燕子)類,但燕子只有飛行能力,所以我們只需要為 Swallow 實現(xiàn) Flyable 就行了。因為它們各自的的飛行方法有所不同,所以它們有各自關于飛行的具體實現(xiàn)。
另外,正因為一個類可以同時實現(xiàn)多個接口,使得Java的面向?qū)ο筇匦宰兊梅浅l`活。運用這種特性,我們可以實現(xiàn)類似C++語言中多繼承那樣的特性,甚至更靈活的一些特性。下面我們來討論一下接口在實際中的應用。
二、用接口來定義一些全局變量
因為接口內(nèi)的字段都是static和final的,所以我們可以很方便的利用這一點來創(chuàng)建一些常量。例如:
public interface Constants {
String ROOT = "/root";
int MAX_COUNT = 200;
int MIN_COUNT = 100;
}
在使用時可以直接用Constants.ROOT這樣的形式來引用其中的常量。我們還可以用下面這種方法來創(chuàng)建初始值不確定的常量。
public interface RandomColor {
int red = Math.random() * 255;
int green = Math.random() * 255;
int blue = Math.random() * 255;
}
其中red、green和blue的值會在第一次被訪問時建立,然后保持不變。
三、用接口來定義基本數(shù)據(jù)結構
在設計一套軟件系統(tǒng)的初期,我們可以用接口來對一些基本數(shù)據(jù)元素的特性來進行一些描述,再根據(jù)需要進行不同的實現(xiàn)。請大家看看下面這個例子:
public interface User {
int getAge();
String getName();
String getPassword();
}
public class XMLUser implements User {
// 這里用XML技術實現(xiàn)User接口中的方法
public int getAge() { ... }
public String getName() { ... }
public String getPassword() { ... }
}
public abstract class UserFactory {
public static UserFactory getUserFactory() {
return new XMLUserFactory();
}
public User getUser(String name);
public User getAdmin();
public User createUser(String name, String password, int age);
public void addUser(User user);
public void delUser(User user);
}
public class XMLUserFactory extends UserFactory {
// 這里用XML技術實現(xiàn)的UserFactory的抽象方法
}
在這個例子中,我們定義了一個接口User和一個抽象類UserFactory。然后我們用XML技術實現(xiàn)這兩個類?梢钥闯觯覀冎恍枰獜挠肬serFactory的getUserFactory()就可以得到一個UserFactory的實例,而不用去考慮這個實例的具體實現(xiàn)方法。通過UserFactory的這個實例我們還可以直接得到User的實例,也不用去考具體的實現(xiàn)方法。
如果我們決定用JDBC技術來實現(xiàn)User和UserFactory,我們只需要按上面的形式實現(xiàn)JDBCUser和JDBCUserFactory就行了。然后把UserFactory中的getUserFactory方法修改一下就可以改變了它們的實現(xiàn)方法。而我們已經(jīng)寫好的調(diào)用UserFactory和User的部分不需要做任何修改。
這是用接口來定義數(shù)據(jù)結構的一個簡單的例子,在實際應用中還有很多靈活的使用方法,大家需要在學習過程中不斷的去體會。
四、理解分布式應用的原理
目前有很多軟件項目都使用了分布式的技術。Java 有多種支持分布式應用的技術,早期用的比較多的有 RMI、CORBA 等技術,而現(xiàn)在 EJB 技術更為流行一些。但這些技術不管怎么發(fā)展,其實都是以接口為基礎的。
以遠程方法調(diào)用 RMI(Remote Method Invocation)為例。在編寫 RMI 應用時,我們需要做兩件最基本的事,首先要定義一個接口,這個接口要繼承 java.rmi.Remote 接口,這個接口中應該包含你要從遠端調(diào)用的方法名。接下來就是寫一個類來實現(xiàn)這個接口中的方法。例如:
public interface Product extends java.rmi.Remote {
String getName() throws java.rmi.RemoteException;
}
public class ProductImpl implements Product {
String name;
public ProductImpl(String n) {
name = n;
}
public String getName() throws java.rmi.RemoteException {
return name;
}
}
在這個例子中,接口 Product 是放在客戶端的,而 ProductImpl 是放在服務器端的,客戶在使用時只需要用指定的規(guī)則得到Product 的實例就行了,不用去考慮 Product 接口里的方法是如何實現(xiàn)的。在定義好這兩個類后,用Java開發(fā)包命令“rmic ProductImpl”就可以幫助我們自動生成兩個類 ProductImpl_Skel 和 ProductImpl_Stub。這兩個類就包含了RMI調(diào)用的運作機制。有興趣的朋友可以把這兩個類反編譯后研究一下。你會發(fā)現(xiàn)其中 ProductImpl_Stub 實際上是接口 Product 的一個實現(xiàn)類。RMI 機制就是用這個類來生成 Product 的實例供客戶端使用。另一個類 ProductImpl_Skel 則是在服務端響應 ProductImpl_Stub 的調(diào)用請求的類。而 RMI 最底層的通訊原理則是利用 ObjectInputStream 和 ObjetOutputStream 通過 Socket 將要調(diào)用的方法名及參數(shù)列表傳到服務器端,服務器端再通過特定的方法調(diào)用實現(xiàn)類(在本例中是 ProductImpl)的對應方法,然后將結果通過 Socket 傳回客戶端就行了。由于 Skel 和 Stub 類是用工具生成的,所以就大大節(jié)省了開發(fā)的時間。另外,如果我們需要修改一些實現(xiàn)方法或錯誤,只需要對服務器端的實現(xiàn)類進行修改就可以了,也就是說這種分布式應用的大部分維護工作在服務器端就可以完成。
現(xiàn)在越來越多的應用使用了 EJB 這種技術。EJB 是從 RMI 發(fā)展而來的一項技術,它比RMI定義得更加完善,可以獲得更好的面向?qū)ο蟮奶匦。但它的?guī)則要比RMI復雜一些。但是不管它多復雜,它同樣是使用了接口來定義各種不同的 Bean,也同樣需要編寫相應的實現(xiàn)類來完成具體的功能,最后還要通過 Socket 來進行通訊。EJB的運作機制本身有一定的復雜性,所以其應用的效率理所當然就會受到一定的影響。因此在選擇開發(fā)技術時應該根據(jù)應用的規(guī)模和特點仔細考慮,不一定流行的技術就一定能適應你的應用。如果你很好的掌握了面向?qū)ο蟮脑O計原則,你就可以自行設計。也許你可以根據(jù)自己應用的特點設計出更合適的分布式應用結構。
五、結論
除了上述的一些應用外,還有很多地方可以使用接口,比如在Java的事件機制中就常用到接口。另外,對于一些已經(jīng)開發(fā)好的系統(tǒng),在結構上進行較大的調(diào)整已經(jīng)不太現(xiàn)實,這時可以通過定義一些接口并追加相應的實現(xiàn)來完成功能結構的擴展。
總之,學好接口可以幫助我們更好的理解和運用面向?qū)ο蟮脑O計原則。使我們能設計出更好的軟件系統(tǒng)。由于本人水平的限制,如有錯誤之處還請多多指正。