【Android】【设计模式】抽象工厂模式改造弹窗组件必知必会

写一个 Android 版本的抽象工厂弹窗 + Manager 管理器 ,使用 DialogFragment 实现,这样能更贴近真实的开发场景。


结构设计

  1. 抽象产品BaseDialogFragment(继承 DialogFragment
  2. 具体产品LoginDialogFragment, UpdateDialogFragment
  3. 抽象工厂DialogFactory
  4. 具体工厂LoginDialogFactory, UpdateDialogFactory
  5. 弹窗管理器DialogManager(统一展示 / 关闭弹窗)

代码实现

抽象产品

java 复制代码
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
    @Override
    public abstract Dialog onCreateDialog(@Nullable Bundle savedInstanceState);

    public void dismissDialog() {
        if (getDialog() != null && getDialog().isShowing()) {
            dismiss();
        }
    }
}

具体产品

java 复制代码
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
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        return new AlertDialog.Builder(requireContext())
                .setTitle("登录")
                .setMessage("请输入账号密码")
                .setPositiveButton("确定", (dialog, which) -> {
                    // 登录逻辑
                })
                .setNegativeButton("取消", null)
                .create();
    }
}
java 复制代码
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
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        return new AlertDialog.Builder(requireContext())
                .setTitle("更新提示")
                .setMessage("检测到新版本,是否更新?")
                .setPositiveButton("更新", (dialog, which) -> {
                    // 更新逻辑
                })
                .setNegativeButton("稍后", null)
                .create();
    }
}

抽象工厂

java 复制代码
public interface DialogFactory {
    BaseDialogFragment createDialog();
}

具体工厂

java 复制代码
public class LoginDialogFactory implements DialogFactory {
    @Override
    public BaseDialogFragment createDialog() {
        return new LoginDialogFragment();
    }
}
java 复制代码
public class UpdateDialogFactory implements DialogFactory {
    @Override
    public BaseDialogFragment createDialog() {
        return new UpdateDialogFragment();
    }
}

弹窗管理器

java 复制代码
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 中调用)

java 复制代码
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onResume() {
        super.onResume();

        // 显示登录弹窗
        DialogManager.showDialog("login", new LoginDialogFactory(), getSupportFragmentManager());

        // 显示更新弹窗
        DialogManager.showDialog("update", new UpdateDialogFactory(), getSupportFragmentManager());

        // 关闭登录弹窗
        DialogManager.dismissDialog("login");
    }
}

✅ 优点:

  • 扩展性强 :新增一个弹窗,只需要新增 DialogFragment + FactoryDialogManager 无需改动
  • 全局管理:可以统一控制弹窗的缓存、复用、显示/关闭逻辑
  • 线程安全 :使用 FragmentManager 管理生命周期,避免内存泄漏

再加一个 全局策略(比如保证同一时间只显示一个弹窗,后来的会自动关闭之前的)

DialogManager 里加一个 全局策略:同一时间只允许显示一个弹窗。这样新的弹窗显示时,会自动关闭之前的。


改造后的 DialogManager

java 复制代码
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; // 当前正在显示的弹窗 key

    public 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;
    }
}

使用示例

java 复制代码
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onResume() {
        super.onResume();

        // 显示登录弹窗
        DialogManager.showDialog("login", new LoginDialogFactory(), getSupportFragmentManager());

        // 这里再显示更新弹窗时,会自动关闭上一个(login)
        DialogManager.showDialog("update", new UpdateDialogFactory(), getSupportFragmentManager());

        // 关闭当前正在显示的弹窗(update)
        DialogManager.dismissCurrentDialog();
    }
}

✅ 这样就具备了:

  1. 抽象工厂扩展性:新增弹窗不用改管理器。
  2. 缓存 & 复用:避免重复创建相同弹窗。
  3. 全局策略:同一时间只显示一个弹窗。
  4. 可选扩展:还能加优先级队列(比如:强制更新弹窗 > 登录弹窗 > 普通提示弹窗)。

相关推荐
00后程序员张6 小时前
怎么用 Egret(白鹭引擎)打包 iOS 应用并上架 App Store?
android·ios·小程序·https·uni-app·iphone·webview
mmsx6 小时前
MapLibre 实战 09|Bug 单写着"地图被风刮走了":一个瓦片源工厂,是三个线上事故换来的
android·前端·开源
一技安身6 小时前
【信创】统信UOS 银河麒麟离线部署Python3.11完整方案
android·java·python3.11
墨狂之逸才7 小时前
Android WebView 初始缩放:什么时候该设置 100%,什么时候不要设置
android
淡淡的香烟7 小时前
AndroidKMP之导航和WebView
android
天空之城--19 小时前
Android逆向安全合规接单指南
android·安全
消失的旧时光-194321 小时前
Android 系统层扫盲 09:AMS、ATMS、WMS、PMS 到底分别管什么?
android·wms·pms·ams·aosp·atms
Godikov21 小时前
Android 系统级设备应用踩坑实录:sharedUserId 签名、SDK 授权失败 -4、开机自启与 U 盘 OTA 升级
android
IT毕设实战小研1 天前
基于大数据的国内主要农作物产量趋势分析与可视化
android·java·大数据·django·课程设计
企业数字化笔记1 天前
固定资产历史数据怎么导入系统?Excel模板、字段映射和数据校验
android·java·数据库·后端