需求分析

以下需求自身很简单,也没有这么离谱的产品司理,没必要杂乱化,咱们更重要的是了解背面的思路。

假设有一个需求:

  1. 随机生成一个杂乱的Key,这个Key包括数字和英文。
  2. 完事后第二天产品司理让你去除Key中的数字。
  3. 第三天让你在结尾拼接个HelloWorld
  4. 第四天让你在结尾拼接个时刻戳
  5. 。。。。
  6. 第十天让你仅仅在结尾拼接个HelloWorld,再拼接个时刻戳
interface IGenerator {
    fun createKey(): String
    fun removeNum(key: String): String
    fun appendHelloWorld(key: String): String
    fun appendTime(key: String): String
}
class GeneratorImpl : IGenerator {
    private var key: String = ""
    override fun createKey(): String {
        key = generate()
        return key
    }
    override fun removeNum(str: String): String {
        //去除数字并返回
        key = str.replace(Regex("\d+"), "")
        return str
    }
    override fun appendHelloWorld(str: String): String {
        key = str + "helloWorld"
        return key
    }
    override fun appendTime(str: String): String {
        key = str + "1999年"
        return key
    }
    private fun generate(): String {
        return "杂乱的Key"
    }
}
fun main() {
    val impl: IGenerator = GeneratorImpl()
    val key1 = impl.createKey()
    val key2 = impl.removeNum(key1)
    //....
}

以上代码带来了什么问题?

  1. 代码臃肿:假如需求加的功用更多呢?GeneratorImpl类中的方法会变得冗长
  2. 代码杂乱度可能会增加
  3. 不灵活:假如后续需求修正某个或增加新的功用,需求直接修正GeneratorImpl类,违反了开闭准则(关于扩展是敞开的,关于修正是封闭的)

装修器形式

咱们先完结第一天和第二天的需求

  1. 随机生成一个杂乱的Key,这个Key包括数字和英文。
  2. 完事后第二天产品司理让你去除Key中的数字。
interface IKeyGenerator {
    fun createKey(): String
}
//第一天咱们完成的功用,生成了一个Key
class KeyGenerator : IKeyGenerator {
    override fun createKey(): String {
        return generateComplexKey()
    }
    private fun generateComplexKey(): String {
        //随机生成了一个杂乱的密钥,包括数字和英文字母
        return "jd3klq5wj1d"
    }
}
//第二天咱们在第一天的基础上,去除了Key中的数字,并没有改动任何第一天中代码
class KeyRemoveNumDecorator(private val keyGenerator: IKeyGenerator) : IKeyGenerator {
    override fun createKey(): String {
        val key = keyGenerator.createKey()
        //去除字符串中的数字
        val newKey = key.replace(Regex("\d+"), "")
        return newKey
    }
}
//调用方法
val keyGenerator: IKeyGenerator = KeyGenerator()
val keyDecorator: IKeyGenerator = KeyDecorator(keyGenerator)
val key = keyDecorator.createKey()
println(key)
打印日志
jdklqwjd

假如看过我上一篇关于署理形式的文章 Android-我对署理形式的了解 – (),你可能会有感触:这不就和静态署理基本上一毛相同吗?这个咱们后面再说。

注释挺详细的,代码也不难了解。

接下来咱们完结第三天的需求:
3. 第三天让你在结尾拼接个HelloWorld

新建类
class KeyAppendHelloWorldDecorator(private val iKeyGenerator: IKeyGenerator) : IKeyGenerator {
    override fun createKey(): String {
        val key = iKeyGenerator.createKey()
        return key + "HelloWorld"
    }
}
调用方法
val keyGenerator: IKeyGenerator = KeyGenerator()
val keyRemoveNumDecorator: IKeyGenerator = KeyRemoveNumDecorator(keyGenerator)
val keyAppendHelloWorldDecorator: IKeyGenerator = KeyAppendHelloWorldDecorator(keyRemoveNumDecorator)
val key = keyAppendHelloWorldDecorator.createKey()
println(key)

接下来咱们完结第四天的需求:
4. 第四天让你在结尾拼接个时刻戳

新建类
class KeyAppendTimeDecorator(private val iKeyGenerator: IKeyGenerator) : IKeyGenerator {
    override fun createKey(): String {
        val key = iKeyGenerator.createKey()
        //伪时刻戳
        return key + "2000年12月20号"
    }
}
使用方法
val keyGenerator: IKeyGenerator = KeyGenerator()
val keyRemoveNumDecorator: IKeyGenerator = KeyRemoveNumDecorator(keyGenerator)
val keyAppendHelloWorldDecorator: IKeyGenerator = KeyAppendHelloWorldDecorator(keyRemoveNumDecorator)
val keyAppendTimeDecorator: IKeyGenerator = KeyAppendTimeDecorator(keyAppendHelloWorldDecorator)
println(keyAppendTimeDecorator.createKey())

到目前为止,咱们扩展新需求,没改动任何原有代码,符合开闭准则(关于扩展是敞开的,关于修正是封闭的)

接下来咱们完结第十天的需求:
6. 第十天让你仅仅在结尾拼接个HelloWorld,再拼接个时刻戳

仅仅修正了调用的方法
val keyGenerator: IKeyGenerator = KeyGenerator()
val keyAppendHelloWorldDecorator = KeyAppendHelloWorldDecorator(keyGenerator)
val keyAppendTimeDecorator = KeyAppendTimeDecorator(keyAppendHelloWorldDecorator)
val key = keyAppendTimeDecorator.createKey()
println(key)

从第十天的需求来看,假如不是增加新的需求,咱们能够仅仅是通过现已存在的功用类进行了自由调配组合完结了任务,尽管调用的方法略显费事些,阅览性差了点意思。

不过也不难了解,首先第一步就是咱们需求先生成keyGenerator对象,而不是直接生成key,接着就是拿着对象按次序塞到你需求的装修器中,最终再生成key。

装修器形式和静态署理形式

这两者都在完成上都是通过持有原始功用的对象的引证,在其基础上增加额外的功用。

灵活性:静态署理形式在编译阶段就确定了署理对象和被署理对象的联系,相对固定。装修器形式能够通过恣意的组合多个装修器,完成不同的行为组合。

针对性:在我上一篇文章署理形式中,我举出的比如针对解耦不大相关的功用。而装修器形式首要针对是解耦相似的功用,使得功用间能够按需组合。

倾向:署理形式相对的更倾向非业务,装修器形式更倾向业务

功用数量:虽然都是扩展新功用,假如增加新功用的概率低,感觉比较适合署理形式。假如功用多且频频变化,感觉更适合装修器形式。