寫一個 Android 版本的抽象工廠彈窗 + Manager 管理器,使用 DialogFragment
實現,這樣能更貼近真實的開發場景。
結構設計
- 抽象產品:
BaseDialogFragment
(繼承DialogFragment
) - 具體產品:
LoginDialogFragment
,UpdateDialogFragment
- 抽象工廠:
DialogFactory
- 具體工廠:
LoginDialogFactory
,UpdateDialogFactory
- 彈窗管理器:
DialogManager
(統一展示 / 關閉彈窗)
代碼實現
抽象產品
import android.app.Dialog;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;public abstract class BaseDialogFragment extends DialogFragment {@NonNull@Overridepublic abstract Dialog onCreateDialog(@Nullable Bundle savedInstanceState);public void dismissDialog() {if (getDialog() != null && getDialog().isShowing()) {dismiss();}}
}
具體產品
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;public class LoginDialogFragment extends BaseDialogFragment {@NonNull@Overridepublic Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {return new AlertDialog.Builder(requireContext()).setTitle("登錄").setMessage("請輸入賬號密碼").setPositiveButton("確定", (dialog, which) -> {// 登錄邏輯}).setNegativeButton("取消", null).create();}
}
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;public class UpdateDialogFragment extends BaseDialogFragment {@NonNull@Overridepublic Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {return new AlertDialog.Builder(requireContext()).setTitle("更新提示").setMessage("檢測到新版本,是否更新?").setPositiveButton("更新", (dialog, which) -> {// 更新邏輯}).setNegativeButton("稍后", null).create();}
}
抽象工廠
public interface DialogFactory {BaseDialogFragment createDialog();
}
具體工廠
public class LoginDialogFactory implements DialogFactory {@Overridepublic BaseDialogFragment createDialog() {return new LoginDialogFragment();}
}
public class UpdateDialogFactory implements DialogFactory {@Overridepublic BaseDialogFragment createDialog() {return new UpdateDialogFragment();}
}
彈窗管理器
import androidx.fragment.app.FragmentManager;
import java.util.HashMap;
import java.util.Map;public class DialogManager {private static final Map<String, BaseDialogFragment> dialogCache = new HashMap<>();public static void showDialog(String key, DialogFactory factory, FragmentManager fragmentManager) {if (!dialogCache.containsKey(key)) {dialogCache.put(key, factory.createDialog());}BaseDialogFragment dialog = dialogCache.get(key);if (dialog != null && !dialog.isAdded()) {dialog.show(fragmentManager, key);}}public static void dismissDialog(String key) {BaseDialogFragment dialog = dialogCache.get(key);if (dialog != null) {dialog.dismissDialog();dialogCache.remove(key);}}
}
使用示例 (Activity 中調用)
public class MainActivity extends AppCompatActivity {@Overrideprotected void onResume() {super.onResume();// 顯示登錄彈窗DialogManager.showDialog("login", new LoginDialogFactory(), getSupportFragmentManager());// 顯示更新彈窗DialogManager.showDialog("update", new UpdateDialogFactory(), getSupportFragmentManager());// 關閉登錄彈窗DialogManager.dismissDialog("login");}
}
? 優點:
- 擴展性強:新增一個彈窗,只需要新增
DialogFragment
+Factory
,DialogManager
無需改動 - 全局管理:可以統一控制彈窗的緩存、復用、顯示/關閉邏輯
- 線程安全:使用
FragmentManager
管理生命周期,避免內存泄漏
再加一個 全局策略(比如保證同一時間只顯示一個彈窗,后來的會自動關閉之前的)
在 DialogManager
里加一個 全局策略:同一時間只允許顯示一個彈窗。這樣新的彈窗顯示時,會自動關閉之前的。
改造后的 DialogManager
import androidx.fragment.app.FragmentManager;
import java.util.HashMap;
import java.util.Map;public class DialogManager {private static final Map<String, BaseDialogFragment> dialogCache = new HashMap<>();private static String currentDialogKey = null; // 當前正在顯示的彈窗 keypublic static void showDialog(String key, DialogFactory factory, FragmentManager fragmentManager) {// 如果有正在顯示的彈窗,先關閉if (currentDialogKey != null && dialogCache.containsKey(currentDialogKey)) {dismissDialog(currentDialogKey);}// 創建或獲取彈窗if (!dialogCache.containsKey(key)) {dialogCache.put(key, factory.createDialog());}BaseDialogFragment dialog = dialogCache.get(key);// 顯示彈窗if (dialog != null && !dialog.isAdded()) {dialog.show(fragmentManager, key);currentDialogKey = key;}}public static void dismissDialog(String key) {BaseDialogFragment dialog = dialogCache.get(key);if (dialog != null) {dialog.dismissDialog();dialogCache.remove(key);if (key.equals(currentDialogKey)) {currentDialogKey = null;}}}public static void dismissCurrentDialog() {if (currentDialogKey != null) {dismissDialog(currentDialogKey);}}public static boolean isDialogShowing() {return currentDialogKey != null;}
}
使用示例
public class MainActivity extends AppCompatActivity {@Overrideprotected void onResume() {super.onResume();// 顯示登錄彈窗DialogManager.showDialog("login", new LoginDialogFactory(), getSupportFragmentManager());// 這里再顯示更新彈窗時,會自動關閉上一個(login)DialogManager.showDialog("update", new UpdateDialogFactory(), getSupportFragmentManager());// 關閉當前正在顯示的彈窗(update)DialogManager.dismissCurrentDialog();}
}
? 這樣就具備了:
- 抽象工廠擴展性:新增彈窗不用改管理器。
- 緩存 & 復用:避免重復創建相同彈窗。
- 全局策略:同一時間只顯示一個彈窗。
- 可選擴展:還能加優先級隊列(比如:強制更新彈窗 > 登錄彈窗 > 普通提示彈窗)。