【Android】【设计模式】抽象工厂模式改造弹窗组件必知必会
写一个 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();}
}
✅ 这样就具备了:
- 抽象工厂扩展性:新增弹窗不用改管理器。
- 缓存 & 复用:避免重复创建相同弹窗。
- 全局策略:同一时间只显示一个弹窗。
- 可选扩展:还能加优先级队列(比如:强制更新弹窗 > 登录弹窗 > 普通提示弹窗)。