0赞
赞赏
更多好文
最近和团队一起重构一个2019年写的项目,代码里全是findViewById、new和各种if-else,连我这个写了8年Android的老手都看不下去了。设计模式不是为了装X,而是让代码在面对需求变更时,不会变成"意大利面"。下面分享我踩过坑后总结的、真正能提升代码质量的5个设计模式用法。
一、别让设计模式变成"代码装饰":先问自己三个问题
在用任何设计模式前,先问自己:
- 这个需求真的需要设计模式吗?(不是"我想用",而是"必须用")
- 这个模式是解决当前问题,还是制造新问题?
- 有没有更简单的方式?
我见过太多团队为了用"工厂模式"硬造一个工厂,结果代码比之前更难读。设计模式不是答案,而是工具——工具用对了,代码就干净;用错了,反而更糟。
二、五个真正能提升代码质量的设计模式(附真实案例)
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最基础的模式,但很多人用得像屎。
我教新人的要点
别用BaseAdapter! 用RecyclerView.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避免重复findViewByIdonBindViewHolder只处理当前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
三、最怕的三种"伪设计模式"(我见过太多人踩坑)
-
"为了用模式而用模式"
例如:一个简单的按钮点击事件,硬要造个"观察者模式",结果代码比原生多3倍。 -
"单例滥用"
把所有工具类都写成单例,结果导致类之间耦合度极高,测试困难。 -
"过度抽象"
一个UserRepository,硬要分成UserLocalRepository、UserRemoteRepository、UserCacheRepository,结果业务逻辑散落在5个文件里。
四、我的终极建议:从"重构"开始
不要一上来就用设计模式,而是从重构开始。当代码出现以下信号时,再考虑设计模式:
- 一个Activity超过500行
- 重复的代码超过3处
- 你发现需要在多个地方修改同一个逻辑
- 测试时需要模拟大量依赖
记住:
设计模式不是为了让你的代码看起来"高级",而是为了让你在需求变更时,不会被代码"杀死"。
最后一句大实话
我见过太多团队用设计模式把简单的项目搞复杂,结果代码比原生更难维护。真正的高质量代码,是让新来的同事在20分钟内能看懂你的逻辑。
设计模式不是答案,而是让你在写代码时,心里踏实的工具。当你能用最简单的模式解决最简单的问题时,你已经是一个优秀的Android开发者了。
