【参与评论有奖】把书读薄 | 《设计模式之美》总结篇(上)

简介: 从六月开始,断断续续,算是把王争的《设计模式之美》看得差不多了,实战部分没来得及看,不过也是获益良多,思维方式上的一些变化。肚子里的墨水不多,不知道如何描述这种感觉,说两个实际的应用场景,读者自行意会哈,顺便带出总结思维导图~

日常开发应用示例一


拿到新的业务需求,不再是直接无脑拆分输出排期,复制粘贴改改代码,而是考虑更多:后续可能有哪些扩展、重复业务能否抽象复用等。举两个例子:


网络异常,图片无法展示
|


1、App里有不同的角色:二级代理、二级负责人、三级代理、三级负责人,然后一个列表页,不同的角色有不同的交互


如果是你用代码实现,你会怎么做?以前的我可能会这样做,把所有逻辑业务都塞到Fragment,一堆if-else


class UserInfoFragment: Fragment() {
    // 加载Fragment
    fun loading() {
        if(isLeader) {
            if (isSecond) {
                // 二级负责人
            } else {
                // 三级负责人
            }
        } else {
            if (isSecond) {
                // 二级代理
            } else {
                // 三级代理
            }
        }
    }
    // 添加客户
    fun addCustomer() {
        if(isLeader) {
            if (isSecond) {
                // 二级负责人
            } else {
                // 三级负责人
            }
        } else {
            if (isSecond) {
                // 二级代理
            } else {
                // 三级代理
            }
        }
    }
    // 还有下面这些,也是如法炮制
    // 搜索
    // 选择代理项目
    // 筛选
    // 排序
    // tab切换
}


写if-else写到想哭,如果再来一类角色,又得套一层if-else,改动量巨大,每个方法都要改。


你可能会说,可以简化判断,定义一个常量属性/枚举来标记一种角色,开头走下判断条件,区分出角色,就不用每次都if-else了:


class UserInfoFragment: Fragment() {
    var role = 0    // 1二级代理人、2二级负责人、3三级代理、4三级负责人
    fun init() {
        if(isLeader) {
            if (isSecond) {
                role = 2
            } else {
                role = 4
            }
        } else {
            if (isSecond) {
                role = 1
            } else {
                role = 3
            }
        }
    }
    // 加载Fragment
    fun loading() {
        when(role) {
            1 -> 二级代理
            2 -> 二级负责人
            3 -> 三级代理
            4 -> 三级负责人
        }
    }


实际上,还是逃避不了判断,当角色发生改变,依旧要动很多代码,怎么写才能保持可扩展性呢?


抽象 + 多态 + 策略模式


可以把 业务逻辑抽象成一个对象,不同的角色进入这个页面,尽管表现不同,但是执行的业务逻辑是一样的,抽象出一个行为接口:


interface IOperate {
    fun loading(container: Int)
    fun addCustomer()
    fun search(select: SelectItem? = null)
    fun selectAgentProject(select: SelectItem? = null)
    fun filter(height: Int, y: Int, select: SelectItem? = null, after: (() -> Unit)? = null)
    fun order(height: Int, y: Int, after: (() -> Unit)? = null)
    fun switchTap(pos: Int)
}


接着定义一个 抽象角色类 来实现这个接口,原则是这样的:


  • 不同角色,相同的逻辑在此重写,相同包括全部相同和部分相同。部分相同指的是部分代码逻辑相同,比如埋点,执行这个逻辑表现不同,但埋点是相同的。子类重写方法,调下super.xxx()复用相同代码,然后重写不同逻辑。


  • 完全不同的逻辑,就不在父类中实现,而是交给具体的子类实现


abstract class Role(protected var mFragment: BaseFragment) : IOperate {
    abstract var type: String   // 描述字段,便于区分而已,没用
    //...
    override fun addCustomer() {
        if (ClickFastUtils.isFastClick()) return
        mFragment.go(AddCustomerFragment::class.java)
        umAddClick.um(mFragment.context)
    }
    override fun filter(height: Int, y: Int, select: SelectItem?, after: (() -> Unit)?) {
        umScreenClick.um(mFragment.context)
    }
    //...
}


然后是 具体角色类,示例如下:


class SecondAgentRole(fg: BaseFragment) : Role(fg) {
    override var type = "二级代理/经纪人"
    override fun loading(container: Int) {
        mFragment.childReplace(SecondAgentListFragment.newInstance(), container)
    }
    override fun filter(height: Int, y: Int, select: SelectItem?, after: (() -> Unit)?) {
        super.filter(height, y, select, after)
        if (select == null) {
            shortToast("您当前不在任何代理项目中挂职,无法查看项目客户!")
            return
        }
        after?.invoker()
        //...其他逻辑
    }
}


接着就到Fragment了,因为 具体逻辑都分化到对应的角色 里了,所以它非常简单:


class CustomerFragment : BaseFragment() {
    override fun initData(bundle: Bundle?) {
        diffRole()?.loading(R.id.fly_content) // 区分用户角色并加载对应Fragment
    }
    // 区分用户角色
    private fun diffRole(): Role? = when {
        isLeader && isSecond -> SecondPrincipalRole(this)
        isLeader && !isSecond -> ThirdPrincipalRole(this)
        !isLeader && isSecond -> SecondAgentRole(this)
        !isLeader && !isSecond -> ThirdPrincipalRole(this)
        else -> null
    }
}


相关文章
|
设计模式 数据处理
【参与评论有奖】把书读薄 | 《设计模式之美》总结篇(下)
从六月开始,断断续续,算是把王争的《设计模式之美》看得差不多了,实战部分没来得及看,不过也是获益良多,思维方式上的一些变化。肚子里的墨水不多,不知道如何描述这种感觉,说两个实际的应用场景,读者自行意会哈,顺便带出总结思维导图~
222 0
|
设计模式 测试技术 uml
把书读薄 | 《设计模式之美》设计模式与范式(行为型-中介模式)
终于来到行为型设计模式的最后一个,中介模式 (Mediator Pattern),本文对应设计模式与范式:行为型(73)。
173 0
|
设计模式 XML 数据格式
把书读薄 | 《设计模式之美》设计模式与范式(行为型-解释器模式)(下)
本文对应设计模式与范式:行为型(72),解释器模式 (Interpreter Pattern),用来描述如何构建一个简单的 "语言"解释器。
139 0
|
设计模式 SQL 编译器
把书读薄 | 《设计模式之美》设计模式与范式(行为型-解释器模式)(上)
本文对应设计模式与范式:行为型(72),解释器模式 (Interpreter Pattern),用来描述如何构建一个简单的 "语言"解释器。
117 0
|
设计模式 uml
把书读薄 | 《设计模式之美》设计模式与范式(行为型-命令模式)(下)
本文对应设计模式与范式:行为型(71),命令模式 (Command Pattern),同样是工作中不怎么常用的模式,了解下即可~
122 0
|
设计模式 开发工具 uml
把书读薄 | 《设计模式之美》设计模式与范式(行为型-备忘录模式)
本文对应设计模式与范式:行为型(70),备忘录模式 (Memento Pattern),又称 快照模式,主要用于 防丢失、撤销、恢复 等,模式很好理解,代码实现比较灵活~
126 0
|
设计模式 Java
把书读薄 | 《设计模式之美》设计模式与范式(行为型-访问者模式)(上)
本文对应设计模式与范式:行为型(68-69),访问者模式 (Visitor Pattern),用于 解耦对象结构与对象操作。 其难点在于代码实现比较复杂,因为大部分面向对象编程语言中是 静态绑定 的。调用类的哪个重载函数,是在 编译期由函数声明类型决定,而非 运行时根据参数实际类型决定 的。 代码实现难理解,在项目中应用此模式可能导致可读性较差,没有特别必要的情况,建议不要使用这种模式~
111 0
|
设计模式 存储
把书读薄 | 《设计模式之美》设计模式与范式(行为型-命令模式)(上)
本文对应设计模式与范式:行为型(71),命令模式 (Command Pattern),同样是工作中不怎么常用的模式,了解下即可~
166 0
|
14天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。