如何用设计模式提高Android代码质量:一个老Android开发者的实战心得

avatar
小常在创业IP属地:上海
02026-02-14:21:40:41字数 4729阅读 0

最近和团队一起重构一个2019年写的项目,代码里全是findViewByIdnew和各种if-else,连我这个写了8年Android的老手都看不下去了。设计模式不是为了装X,而是让代码在面对需求变更时,不会变成"意大利面"。下面分享我踩过坑后总结的、真正能提升代码质量的5个设计模式用法。


一、别让设计模式变成"代码装饰":先问自己三个问题

在用任何设计模式前,先问自己:

  1. 这个需求真的需要设计模式吗?(不是"我想用",而是"必须用")
  2. 这个模式是解决当前问题,还是制造新问题?
  3. 有没有更简单的方式?

我见过太多团队为了用"工厂模式"硬造一个工厂,结果代码比之前更难读。设计模式不是答案,而是工具——工具用对了,代码就干净;用错了,反而更糟。


二、五个真正能提升代码质量的设计模式(附真实案例)

1. 单例模式:别让Application成为内存泄漏的温床

为什么用?
管理全局状态(用户信息、配置)时,单例比到处传Context省心。但Android里用错,分分钟内存泄漏。

我的血泪教训
之前写了个UserManager单例,直接持有Activity引用:

class UserManager private constructor() {
    private lateinit var context: Activity // 错!
    companion object {
        val instance = UserManager()
    }
}

结果Activity销毁后,单例还挂着,内存泄漏。现在我直接用枚举单例+Application Context

object UserManager {
    private var appContext: Context? = null
    fun init(context: Context) {
        appContext = context.applicationContext
    }
    fun getCurrentUser(): User? = ... // 用appContext,安全!
}

关键点

  • 永远别在单例里存Activity/Fragment的引用
  • getApplicationContext()而不是Activity的Context
  • 用Kotlin的object代替Java单例,避免手动实现

2. 观察者模式:LiveData才是Android的"真·观察者"

为什么用?
UI和数据状态联动(列表刷新、登录状态更新),用观察者比手动注册/注销简单10倍。

我改写的真实案例
之前用BroadcastReceiver管登录状态,注册/注销到处写:

// 旧代码:到处注册,容易漏
registerReceiver(...)

现在直接用LiveData+ViewModel

class LoginViewModel : ViewModel() {
    private val _isLoggedIn = MutableLiveData<Boolean>()
    val isLoggedIn: LiveData<Boolean> get() = _isLoggedIn

    fun login() {
        // ...登录逻辑
        _isLoggedIn.value = true
    }
}

在Fragment里:

viewModel.isLoggedIn.observe(this) { isLogged ->
    if (isLogged) showMainScreen()
}

为什么爽?

  • 生命周期自动管理!Activity销毁时自动取消订阅
  • 不用担心内存泄漏
  • 代码量减少50%+,可读性大幅提升

注意:别用RxJava做简单状态管理,LiveData更轻量,Android原生支持。


3. 工厂模式:别让Fragment创建逻辑烂在Activity里

为什么用?
当需要根据条件创建不同Fragment时(比如不同用户角色),工厂模式能解耦Activity。

我重构的代码
之前写:

// Activity里硬编码
val fragment = if (user.isAdmin) AdminFragment() else UserFragment()

现在用工厂:

class FragmentFactory {
    fun createFragment(user: User): Fragment {
        return when {
            user.isAdmin -> AdminFragment()
            user.isGuest -> GuestFragment()
            else -> UserFragment()
        }
    }
}

在Activity里:

val fragment = FragmentFactory().createFragment(currentUser)
supportFragmentManager.beginTransaction().replace(R.id.container, fragment).commit()

好处

  • Activity只负责"要什么",不关心"怎么造"
  • 新增角色只需改工厂,不碰Activity
  • 未来新增角色,比如VIPFragment,只需加一行代码

4. 适配器模式:RecyclerView.Adapter的"真谛"

为什么用?
把数据源(List)适配到UI组件(RecyclerView),这是Android最基础的模式,但很多人用得像屎。

我教新人的要点
别用BaseAdapterRecyclerView.Adapter+ViewHolder

class ProductAdapter(private val items: List<Product>) : 
    RecyclerView.Adapter<ProductAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_product, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(items[position]) // 这里才是适配的核心
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(product: Product) {
            itemView.tvName.text = product.name
            itemView.ivImage.load(product.image)
        }
    }
}

关键点

  • ViewHolder避免重复findViewById
  • onBindViewHolder只处理当前item,性能碾压旧版
  • 适配器只关心"如何显示数据",不关心"数据从哪来"

5. 策略模式:RecyclerView的LayoutManager,你真的懂吗?

为什么用?
当有多种算法(比如列表布局:线性/网格/瀑布流),策略模式让切换更简单。

真实场景
之前在Activity里写布局逻辑:

// 旧代码:硬编码
val layoutManager = if (isGrid) GridLayoutManager(...) else LinearLayoutManager(...)

现在用策略:

interface LayoutStrategy {
    fun createLayoutManager(context: Context): RecyclerView.LayoutManager
}

class GridStrategy : LayoutStrategy {
    override fun createLayoutManager(context: Context) = 
        GridLayoutManager(context, 2)
}

class LinearStrategy : LayoutStrategy {
    override fun createLayoutManager(context: Context) = 
        LinearLayoutManager(context)
}

在Adapter里:

fun setLayoutStrategy(strategy: LayoutStrategy) {
    recyclerView.layoutManager = strategy.createLayoutManager(context)
}

为什么值?

  • 切换布局只需adapter.setLayoutStrategy(GridStrategy())
  • 未来新增瀑布流,只需加新策略类,不改Adapter

三、最怕的三种"伪设计模式"(我见过太多人踩坑)

  1. "为了用模式而用模式"
    例如:一个简单的按钮点击事件,硬要造个"观察者模式",结果代码比原生多3倍。

  2. "单例滥用"
    把所有工具类都写成单例,结果导致类之间耦合度极高,测试困难。

  3. "过度抽象"
    一个UserRepository,硬要分成UserLocalRepositoryUserRemoteRepositoryUserCacheRepository,结果业务逻辑散落在5个文件里。


四、我的终极建议:从"重构"开始

不要一上来就用设计模式,而是从重构开始。当代码出现以下信号时,再考虑设计模式:

  • 一个Activity超过500行
  • 重复的代码超过3处
  • 你发现需要在多个地方修改同一个逻辑
  • 测试时需要模拟大量依赖

记住

设计模式不是为了让你的代码看起来"高级",而是为了让你在需求变更时,不会被代码"杀死"。


最后一句大实话

我见过太多团队用设计模式把简单的项目搞复杂,结果代码比原生更难维护。真正的高质量代码,是让新来的同事在20分钟内能看懂你的逻辑。

设计模式不是答案,而是让你在写代码时,心里踏实的工具。当你能用最简单的模式解决最简单的问题时,你已经是一个优秀的Android开发者了。

总资产 0
暂无其他文章

热门文章

暂无热门文章