簡體   English   中英

Java:使用多態來避免if語句?

[英]Java: using polymorphism to avoid if-statements?

我正在嘗試編寫一個java程序,根據用戶選擇的內容初始化某些布局。 我想要做的是盡量避免編寫一堆if語句,以便在需要添加更多布局時,代碼可以擴展以供將來使用。 我聽說實現這個的最好方法是使用多態,但我對多態的理解仍然有點模糊。

說我想實現這個案例:

if (user choose layoutA) { initialize layoutA }
if (user choose layoutB) { initialize layoutB }
if (user choose layoutC) {initialize layoutC }

我正在考慮為要實現的類創建一個接口。 令我困惑的是它在main()中是如何工作的,我是否還需要一個條件if或switch語句來確定實例化哪個類?

interface LayoutHandler {
    public void initializeLayout();
}

class layoutA implements LayoutHandler { 
    public void initialize Layout {initialize layout A}
}
class layoutB implements LayoutHandler { 
    public void initialize Layout {initialize layout B}
}
class layoutC implements LayoutHandler { 
    public void initialize Layout {initialize layout C}
}

然后在主要的某個地方:

public static void main() {
   getlayoutselectionfromuser()
   if (user choose layoutA) { LayoutHandler layout = new layoutA(); }
   if (user choose layoutB) { LayoutHandler layout = new layoutB(); }
   if (user choose layoutC) { LayoutHandler layout = new layoutC(); }

}

我是否仍然需要在主程序中使用switch或if語句來確定用戶在運行時選擇的布局?

謝謝!

通常,在某些時候很難避免某種條件語句來創建適當類的實例。

當多個地方有多個if-else語句時,就會產生多態性的好處。 多態性為您封裝了條件邏輯。 有關此主題的其他討論,請參閱此問題

這種分散的邏輯:

void initLayout() {
   if (user choose layoutA) { initialize layoutA }
   if (user choose layoutB) { initialize layoutB }
   if (user choose layoutC) {initialize layoutC }
}

void refreshLayout() {
   if (user choose layoutA) { refresh layoutA }
   if (user choose layoutB) { refresh layoutB }
   if (user choose layoutC) { refresh layoutC }
}

void cleanupLayout() {
   if (user choose layoutA) { cleanup layoutA }
   if (user choose layoutB) { cleanup layoutB }
   if (user choose layoutC) { cleanup layoutC }
}

獲取替換為更簡單的東西:

   layout = getLayout(user choice);

   layout.initLayout();
   layout.refreshLayout();
   layout.cleanupLayout();

由於java沒有第一類函數,因此可以使用接口進行環繞。

LayoutHandler ~> Interface

LayoutHandlerA, LayoutHandlerB, etc implements LayoutHandler

Map<String, LayoutHandler> handlers = new HashMap<...>();

LayoutHandler handler = handlers.get(userSelectedLayout);

handler.handle();

簡而言之,是的。 你需要ifs或一些映射機制。

您需要一些方法將用戶的輸入轉換為您想要的類。 你的代碼中的ifs工作得很好,清晰可讀。 你也可以使用開關。

可以避免這種情況,但是你最終會混淆你的代碼,最終可能會有類似if的東西。 您必須定義從用戶輸入到對象的映射; 那是無法規避的。 最清晰,最可維護的方法就是你已經擁有的東西(雖然我會把其他ifs放在那里。:))

你對每個布局都有不同類的想法也不錯。 這很像一個特質類的概念。 看看那個。 它對您的設計很有幫助。

不。使用地圖。 當你得到選擇時,只需在地圖中查找處理程序然后離開即可。

偽碼

 Map handlers = new Map()
 handlers.put(layoutA, HandlerForA)
 // more handlers, possibly use dependency injection

 Layout chosen = user choose layout // get a ref to the selected layout
 Handler handler = handlers.get(chosen)
 if (handler == null) { // No HandlerException }
 handler.go()

只有一個if語句。

某個地方需要指定實施。 這可能是源代碼中的if語句鏈 - 但它也可能是其他東西; 例如,在外部數據源中指定的類名,通過反射實例化。

對於某些接口,可能會有比實例化更多的接口調用。 多態性可以減少與特定實現的耦合。

這種減少的耦合可以幫助使代碼更易於維護。 您可以添加新實現,而無需修改可能的許多調用方。

我在你的代碼架構上“模糊不清”,但我的想法是你只在一個地方安裝了交換機而不是在你的代碼中散布多個交換機,這些交換機除了正在運行的對象之外具有相同的功能簽名。

確切的實現取決於你的目標是什么,但我認為你會有一個實現LayoutHander的類,並且有一個成員引用布局。 當用戶選擇他的布局時,多態性在這里保持,而不是現在的等級。 也就是說,如果定義不同行為的對象是“布局”,那么您需要使布局具有多態性,而不是LayoutHander。

當您考慮多態性時,請考慮重用代碼。 “這些相關的功能與不同的對象有什么共同之處?”

我認為使用if語句進行初始化很好。 您試圖避免在整個程序中重復使用if語句來“選擇”行為。 使用if語句進行一次初始化很好。

可以肯定的是,有一些方法可以避免那些初始化if語句,但你必須決定什么級別的復雜性和可能的​​可讀性損失適合你的應用程序。

例如,以下是從簡單到復雜的這個問題的一些方法:

  • 使用那些初始化if語句
    • 使用硬編碼引用直接在程序邏輯中實現類(更難找到)
  • 使用可能的實現類初始化一些數據結構(例如Map)
    • 仍然是對實現類的硬編碼引用
    • 通常更容易添加更多的實現類
    • 代碼有點復雜和抽象,無法理解和調試
  • 使用動態注冊
    • 沒有對應用程序中的實現類的硬編碼引用
    • 需要更多設置
    • 在不知道如何設置注冊工作的情況下,代碼更難理解

最后一個方法(動態注冊)的一個很好的例子是查看JDBC的工作原理。 使用Class.forName()在應用程序中注冊JDBC驅動程序,然后使用JDBC URL選擇特定的JDBC驅動程序。 這是一個典型的工作流程:

  1. 潛在目標JDBC驅動程序添加了類路徑。

  2. 應用程序配置了這些驅動程序的列表,例如通過在屬性文件中列出JDBC驅動程序。

  3. 應用程序通過在列表中的每個驅動程序上調用Class.forName()來初始化。 Class.forName()加載時,每個驅動程序都知道用DriverManager注冊自己

  4. 應用程序確定要使用的目標數據庫資源,並將其解析為JDBC URL,例如在配置對話框或用戶提示符中。

  5. 該應用程序要求DriverManager根據目標JDBC URL進行連接。 DriverManager輪詢每個已注冊的驅動程序,以查看它是否可以處理目標JDBC URL,直到DriverManager找到有效的URL。

這將是避免那些if語句的相反極端。

“..如果需要添加更多布局,以供將來使用”

我也建議你研究工廠模式。 如果在工廠中包含此條件邏輯,它應該有助於降低維護和可讀性。

您應該使用框架來避免創建o定義行為。

Spring讓我們可以管理和解決這個問題。 它使用工廠模式和更多設計模式。 因此,使用注釋或xml配置文件,您可以決定創建哪些類。 PD:當然,我是100%安全,春天使用if。 但它已被證明並用於許多強大而可靠的應用程序中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM