设计模式

前言

今天跟一哥们聊到了设计模式, 我突然断路了, 只想到了单例. 后来自己想了想, 其实在我自己的工程中用到了很多设计模式, 现在来总结一下.

设计模式

单例模式

单例一般是用在只想在程序中有一个实例, 一般对于资源的持有. 比如各种 Mgr .
单例需要注意的地方是接口的线程安全问题了.
最明显的一个就是初始化时的线程安全处理了.

初始化时的线程安全我一般会这样做, 使用同步锁, 在一些不同语言上, 可能还需要做双重检查.

伪代码:

if (null == gInstance) {
    lock
    if (null == gInstance) {
        gInstance = new instance();
    }
}
return gInstance

代理模式

就如代理这个名字而言就知道, A 不直接操作 B , 而是创建一个 ProxyB , 然后让 A 去操作 ProxyB 的接口, ProxyB 最终再去调用 B .

为什么要这样做, 是做了结构而清晰, A 可以直接操作 B, 但是这样会让 A 中见到太多根本 A 不需要知道的属性, 类, 等等. 从而让 A 中逻辑上而复杂, 更庞大. 而 A 其实只是想在这个功能, 只不想见到 B 的细节.

简而言之, 代理本身并不提供实际功能, 它的功能都是被代理对象提供的. 只是有了它, 它可以把被代理者的接口简化, 同时, 还可以适应多种的被代理对像. 就像 Proxy 同时代理 B1, B2, B3. 然后 A 都可以通过 ProxyB 对调用 B1, B2, B3 的功能.

装饰器模式

这个模式我自己写得少, 但是我用得挺多的.

装饰器更像是一种扩展, 在原来的类上扩展了功能, 简单的理解, 可以理解为添加了函数.

工厂模式

这个简单来说, 就是通过工厂来创建真实的类. 外层的调用者不用管创建的真实类是什么, 只需要调用实例就可以了.

从这里可以看出, 它屏蔽掉了实例的创建, 外层只管调用.

观察者(订阅)模式

这个也是一个比较常用的方法. 最常见的是, A 对 Data 的变化情况很感兴趣, 那么 Data 就可以添加一个观察者模式, A 对 Data 感兴趣, 那 A 可以在 Data 上注册一个监听, 当 Data 的数据有变化时, 就可以通过监听通知 A 了, 同时, 如果 B 也对 Data 感兴趣, 一样的, 也可以注册一个监听. 当 Data 的数据变化时, 会同时通知 A 和 B .

这里要说明的一点是, Data 并不会关心, 到底是谁在监听, 所以 Data 是不会持有 A/B 的, 但是它会持有一个 DataObserver 类, 也就是 A/B 会实现这个类. 所以 DataObserver 是 A/B 与 Data 之间的桥梁, Data 不关心谁在监听, 只要你实现在 DataObserver , 就可以监听 Data 的状态了.

EventBus

这不是一个大家都公认的模式, 更像是一个小型的库.

但是我觉得用这个来做解耦特别好, 比如我们这里有一个 EventBus, 然后有一些模块(比如A) 对事件 EventName1 关心, 所以监听了 EventName1 . 当模块 B 发生了 EventName1 事件, B 可以通过 EventBus 发送 EventName1 事件. 然后所以监听 EventName1 的模块都可以收到这个事件.

而监听者 A 与发送者 B 之前其实并无联.

组合

这个也不是通常我们说的设计模式, 但是组合这种方式在游戏中特别常见. 而且这种方法的确很适用一些场景.

组合与我们常说的继承是不一样的, 组合是说把功能都分开, 当需要什么, 我们就把它们组合成一个新的实例.

比如我们有功能 Fly, Walk, Swim .
那么我们可以创建一个基本类, 比如 NodeA , 然后让 NodeA 持有 Fly , Walk,
再创建一个 NodeB, 让 NodeB 持有 Walk, Swim.
这样我们就有一两个实例, A 会飞同时也会走路. B 会走路同时也会游泳 .

这种方法的很自由, 可以很方便地构建自己的类.
不好的地方就是组件与组件之间的查找有点烦锁.

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容