架构师_设计模式之六大原则,及其模式总结
设计模式六大原则:
1.单一职责 2.开闭原则 3.里氏替换原则 4.依赖倒置原则 5.接口隔离原则 6.迪米特法则
模式总结:
设计模式:
创建型模式:1.简单工厂 2.单例模式 3.原型模式 4.建造者模式
结构型模式:6.桥接模式 7.组合模式 8.装饰器模式 9.外观模式 10.享元模式 11.适配器模式 12.代理模式
行为型模式:12.模板方法 13.责任链模式 14.命令模式 15.迭代器模式 16.中介者模式
17.备忘录模式 18.观察者模式 19.状态模式 20.策略模式 21.访问者模式
六大原则:只是对我们写代码的一种指导性建议,也可以不遵守,按照自己风格写,但是写完之后,维护起来就是一团乱麻,而遵守了六大原则,就是提高代码的稳定性 可拓展,健壮性
为什么很多设计模式都差不多? 解决的问题不同,所以取了不同的名字,(就像水库抽水和放水,它们都是水没了,一个抽水是为了抓鱼,一个放水是为了泄洪,但是解决办法都是把水减少)
定 义:一个类只负责一项职责,不要存在多余一个导致类变更的因素
反面例子:A类游泳池,负责游泳功能和跳水功能,当某一天,游泳功能改为跑步, 那么A类势必要进行改造,从而影响跳水功能
解决方案:遵循单一职责,游泳就为游泳类,跳水就为跳水类
好处:类遵循单一职责,增加代码扩展性,代码很简单,不一定需要遵守。方法遵循单一职责增加程序稳定性,每个方法都可以独立演变
定 义:类,函数,模块, 拓展开发,修改关闭
反面例子:一个类,如果是祖传代码,你直接去修改,不知道他涉及到什么功能
解决方案:软件需要变化的时候,尽量拓展来满足需求,而不是直接去修改它,拓展之后的业务逻辑都是自己的,改起来so easily
定 义:子类可以扩展父类的功能,但不能改变父类原有的功能
反面例子:继承带来好处,但是也带来了弊端,当一个类被其他类继承到时候,修改这个类,必须要考虑到所有的子类功能是否会产生问题
解决方案:
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类中可以增加自己特有的方法。
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
- 子类继承父类的时候,不要使用new这个关键字去隐藏
- 尽量左边使用父类申明 父类=new 子类 不要用 子类=new子类 如果子类使用了new隐藏了方法,那么就会出现问题
定义; 核心思想就是面向接口编程,高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
反面例子:三层 ui>bll>dal ui高层非常依赖bll层
解决方案: ui和bll层中间抽象一个IBll层 这样改动bll层就不会直接印象ui层,同理dal和bll也可以抽象出一个IDAL层
定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
反面例子:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
解决方案:将臃肿的接口I拆分为独立的几个接口 按功能划分(接口分拆),类去继承多个分拆的接口(接口多继承)。也就是采用接口隔离原则。
接口隔离原则的意义:就是需要按照业务怎么去拆分成小粒度的接口,合适自己的业务就行
定义:一个对象应该对其他对象保持最少的了解。高内聚 低耦合
反面例子:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
解决方案:尽量降低类与其他类之间的耦合。 只和自己直接的类联系 三层架构就是迪米特法则的最佳例子
创建型模式总结:关注对象的创建,把对象的创建进行转移,复制,克隆
结构型模式总结: 关注类与类之间的关系,继承,组合,依赖, 包一层,用新的类来进一步封装原先的类
并且组合优于继承 目的就是降低类与类直接的耦合
1.为什么组合会优于继承?,因为子类继承父类,父类会把所有方法都给子类,不管要不要
2.只能为单一类型服务
三种组合方式:属性字段注入 构造函数注入 方法注入
目的就是降低对象和行为直接的耦合
孤立存在的类是没有意义的 面向对象思想决定了类与类是交互的
类与类之间的关系的分为纵向与横向:
纵向:层级关系,继承与实现(is-a-kind-of) 横向:平级关系,组合-聚合-关联-依赖
对 象:产品类 工厂类 抽象产品类
使用条件: 复杂的对象创建 用户不自己创建对象,而是由工厂来创建。 传一个值给工厂,工厂给你创建对应的对象
例 子: 用户class去工厂class买鞋class, 鞋clss是由工厂实例化的 而不是你用户来生产的,你只需要找到工厂 说明你要买的那种鞋,工厂就是给你需要的鞋
2.抽象工厂模式_创建型模式:
对 象:产品类 抽象产品类 工厂类 抽象工厂类
使用条件:比简单工厂复杂的对象创建 用户不自己创建对象,而是由抽象工厂里面的具体工厂来创建
例 子: 用户去小米买键盘产品, 键盘产品是继承与,抽象小米产品的, 抽象小米产品下面 有很多小米手机,红米手机,
对 象: 实例化当前类的时候 只需要实例化一次
使用条件:多个对象,其需要实例化一个对象,全局只允许存在一个实例class
例 子:数据库连接
对 象: 原型类 具体原型类1.2.3 实现克隆
使用条件:创建重复对象,保证性能,为什么性能快(因为使用的是内存拷贝,对象直接拷贝,而不是去重新构造一个函数,并且计算机内存操作速度是最快的)
例 子:qqvip,,qqvip每个有都有这个对象,但是每个qq vip等级不同,就会展示不同东西,
围棋棋子对象,都是用的棋子对象,只是颜色位置不一样
对 象:指挥者 具体建造者(工人) 抽象建造者(工人) 产品
使用条件:比工厂方法更加复杂的对象创建。流程固定,
例 子: 建一栋房子, 有水泥工, 砌墙工,钢筋工, 他们的建造流程都由指挥者控制,先造地基,再建框架,流程不能乱 工人配好水泥钢筋产品
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class: 苹果手机类,抽象手机类 ,系统类,抽象系统类
使用条件: 解决多维度的变化,多重继承与变化封装
例 子: 苹果,华为,手机,都有自己的系统, 但是也可以刷机成,ios和andor系统, 如果手机和系统耦合太高,那么每一个系统和型号的改变,苹果手机类就要发生改变
class:
使用条件: 适用于 树形结构,递归自己
例 子: 我们的C盘里面就是一个树形结构,你不知道里面有多少个文件夹,但是现在要找出来c盘下面A文件里面的文件数量 就可以用递归实现 你只需要知道C://A文件盘位置
组合模式分为安全和透明模式 有父类和子类
安全:就是子类自己有递归方法
透明:就是父类自己有递归方法,这就造成了,子类继承父类的时候必须继承它的递归方法,会报错,需要忽略这个错误
8.装饰器模式_结构型:面向切面编程 (AOP) 动态的添加功能 结构模式的巅峰之作:组合+继承
class: 类与类直接的关系 降低耦合
使用条件: 希望能够动态增加功能+只有调整功能只需顺序
例 子: 动态的添加功能 动态的给对象添加 层级功能 每一层都是单独的 可变顺序的,就像人穿衣服一样,每一件衣服都是独立的,材质,品质不同,也可以先穿外套,再穿内衣
class: UI BLL DAL
使用条件: 比较简单,就是多一层接口,降低UI与DAL层的直接交互
例 子: 经典的三层架构, 就是避免了ui层直接访问DAL数据层, 从而有了BLL业务逻辑层
旧有的系统与新系统之间的联系,可以使用外观模式, 都访问中间facade 来避免旧有系统持续扩大,和业务逻辑的管理 减少类之间的依赖
class: 类, 抽象类 抽象类中有公用的属性 类里面有自己私有的属性
使用条件: 把对象相同的属性归于一个类,其他不同属性通过外部类传递进来, 减少对象的重复创建
例 子: 就像斗地主一样,56张牌 new56个对象,三个人就占了56个内存地址, 那么一个棋牌平台估计经不起这么折腾,
他们区别就是里面的数字 花色不同,把这个提出来, new一个扑克对象, 里面包含一个类 而这个类的属性字段有:数字花色
11.适配器模式_结构型: 不需要在项目刚设计的时候使用 是属于一种项目已经设计好,后期需求补救的一种方式
对 象: (江西人class,新疆人class 抽象class类) 适配器类 美国人类
使用条件: 把不能用的类,通过适配,变的可以一起使用
例 子: 江西人,新疆人都是中国人都会说中国话,但是如果想要使用美国人,那么久需要适配器(相当于翻译人员),这样就可以放在一起使用
对 象: 类 代理类 实现类
使用条件: 类不直接与实现类关联,而是创建一个代理来执行。代理类不能扩展业务逻辑,代理是没资格更改本来实现的业务逻辑,但可以扩展公共逻辑,加日志,缓存之类的
例 子: 火车站售票处,彩票窗口, 不可能自己直接去火车上买吧, 当然也有这种情况,那么就会出现堵塞,权限也控制不了,还没有秩序
缓存代理:封装一个第三方缓存, 在代理里面进行缓存操作 提升性能 性能提升 优先考虑缓存
单例代理: 代理类里面做好单例
异常代理: 代理类里面做好异常控制
延迟代理:队列 前端延迟加载 一切可以推迟的东西晚点再做 按需加载 类初始化的时候为空,在方法执行的时候再去实例化
权限代理:鉴权-授权-认证 CallContxt 一个写 一个查 放在一个共享的地方
AOP:面向切面核心追求,不破坏封装的前提下,动态扩展功能
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class: 类,抽象类 定义一个抽象父类,实现通用的处理流程 对于不同业务在抽象父类提供抽象方法,由不同子类去实现
使用条件: 应对在一个长业务固定流程中,环节可扩转变化就可以使用模板方法,对于部分相同业务在抽象父类提供虚方法,默认为父类方法,子类可重新定制个性化需求
例 子: 可变的和不可变的混在一起,把不可变的提取出来,做成公共的 同样的车,有公共的配置,大家都是四个轮胎,一个方向盘,但是有的人的车,需要车内饰个性化定制
class: 请求人, 请求的数据, 审批人
使用条件: 一条请求,需要流传到各个对象手里,但是各个对象审批顺序可以变化。
可以把请求结构包装存到一个第三方contenxt 也是责任链模式的标致, 审批过程中的节点动态扩展及更改
例 子: 请假审批,给主管 经理 ceo
class: 请求者 抽象命令 具体命令, 执行者
使用条件: 需要发送一个请求,并且这个请求有相关命令,且数据很重要,需要实时备份 调用者将请求封装,>请求封装成命令对象,>最后发送给执行者,
命令>执行者 中间就可以做成异步队列服务,保存好命令集,哪怕数据库崩了,也可以执行命令集来恢复
例 子: 各种app付款指令>到数据库。如果每天凌晨0点备份 万一早上九点数据库损坏, 那么0点-9点的这段时间 就可以用命令来执行恢复
class:
使用条件: 需要循环的数据集合 list,数组,提供统一访问方式 如果不用foreach 迭代他们是需要不同的访问方式的
例 子: foreach 就是c# 完美实现了迭代器模式
class: 发送类 中介类 接收类 (用户 角色 权限)
使用条件: 点到点需要变成点到面,
例 子: 群发消息下班,如果人事说要下班,没有中介者,那么需要一个个找到并通知,现在只需要通过邮件这个中介发送给大家
常见的就是我们系统程序的 用户 角色 和UI 管理者和普通用户展现的页面菜单不一样 用户拥有管理者角色 可以访问后台菜单 但是后台菜单可以给多个角色
class: 发起人 备忘录(第三方容器),管理者(负责发起人的存档和加载行为)
使用条件: 保存某种进度,备份行为
例 子: 游戏保存进度
class: 观察者 抽象观察者 主题 具体主题
使用条件: 发布订阅的时候 一个接口需要把数据分发给不同的数据平台
例 子: 多播委托是最好的解决方案
class: context state 具体state
使用条件: 不同状态,执行不同行为,消除庞大的分支判断条件
例 子: 地铁闸门。投票行为, 避免恶意刷票
class: contenxt 抽象算法策略类 具体算法策略类
使用条件: 各种运用到算法的地方
例 子: 计算器,商场打折,营销活动
class: 抽象客户 普通客户 VIp客户 访问者 客户的具体行为
使用条件: 固定场景, 客户这个类型是固定的不能变化,因为这个是最底层,
例 子: 表达式目录树就是使用访问者模式,我们使用表达式目录树的时候 把lambda ()=> m*n+1给访问者 他首先会使用递归一步步进行二元化拆解放进去进去是 左边:M*n 和右边:+1 第一步拆解下就是 左边M 右边N
去酒吧, 酒保就是访问者 当VIP客户去酒吧的时候 酒保会自动把你带到VIP客户区 然后VIP客户区 又分为 有拖的 和没拖的 然后有拖的买1W的酒 没拖的买啤酒 最后让你坐下嗨皮 访问者把你客户需要做的 都给你拆解好了 最终你过去直接坐下就好 普通客户来了也只需要交给酒保 直接坐下 给你安排的合理
10.享元模式
本文来自博客园,作者:12不懂3,转载请注明原文链接:https://www.cnblogs.com/LZXX/p/12876688.html