设计模式六大原则

设计模式六大原则:

1. 单一职责原则(SRP)

​ 每一个只有一个原因引起类变化,理想情况下是这么设计,但现实因为类分工的标准不一样,导致类功能分离的程度不一样,所以现实中一般是对接口进行单一职责原则的定义

​ – 将接口的职能单一化,类功能也尽量单一功能话,后续的维护、可读性会增加,不过文件数会增加

2.里氏替换原则(LSP)

​ 看到名字,感觉好高大的样子,也对这个原则的名字充满疑惑。其实原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的 。

有二类定义:
1. 如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 	o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型  (最正宗的定义)
2. 所有引用基类的地方必须能透明地使用其子类的对象 

第二个定义是最清晰明确的,通俗点讲,只要父类能出现的地方子类就可以代替父类出现,但是反过来,有子类出现的地方,父类未必能适用。里氏替换原则为良好的继承定义了一个规范,其中包含了4层含义:

  1. 子类必须完全实现父类的方法

    父类接口里申明的方法子类中必要要有对应的实现方法,所以父类出现的地方子类可以替代

  2. 子类可以有自己的个性

    里氏替换原则是可以正着用,即子类可以替换父类,但是不能父类替换子类,因为子类中会有自己的“个性”,即方法和属性

  3. 覆盖或实现父类的方法时输入参数可以被放大

  4. 覆盖或实现父类的方法时输入参数可以被缩小

    public class Father {
    
        public Collection doSomthing(HashMap map){
            System.out.println(" Father doSomthing.....");
            return map.values();
        }
    
        public Collection searchSomthing(Map map){
            System.out.println(" Father searchSomthing.....");
            return map.values();
        }
    }
    
    public class Son extends Father{
    
        //TODO 放大参数范围 --> 这个是属于方法的 Overload
        public Collection doSomthing(Map map) {
            System.out.println(" Son doSomthing.....");
            return map.values();
        }
    
        //TODO 缩小参数的范围 --> 这个是属于方法的 Overload
        public Collection searchSomthing(HashMap map) {
            System.out.println(" Son searchSomthing.....");
            return map.values();
        }
    }
    
    public class Client {
    
        public static void main(String[] args) {
            Father father = new Father();
            //        Father doSomthing.....
            father.doSomthing(new HashMap());
    
            Son f = new Son();
            // 此处调用的时候可以发现2个doSomthing 方法,参数不同
            //        Father doSomthing.....
            f.doSomthing(new HashMap());
    
            //        Son doSomthing.....
            f.doSomthing(new ConcurrentHashMap());
    
            //      Father searchSomthing.....
            father.searchSomthing(new HashMap());
    
            //       Son searchSomthing.....  比较上面的 2个参数一样 结果不一样
            f.searchSomthing(new HashMap());
        }
    
    
    }
    

在项目中,才有里氏替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子类和父类之间的关系就很难调和了,把子类当作父类使用,子类的个性被抹杀——委屈了点;把子类单独作为一个业务来使用,则会让代码间的耦合关系变得扑朔迷离——缺乏类替换的标准。

3. 依赖倒置原则(DIP)

High level moduls should not depend upon level modules.Both should depend upon abstractions.

  • 高层模块不应该依赖低层模块,两者都应该依赖其抽象

Abstractions should not depend upon deatils.

  • 抽象不应该依赖实现细节

Details should depend upon abstractions.

  • 实现细节应该依赖抽象

每一个业务逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块,而原子逻辑的再组装就是高层模块,而再Java语言中抽象指的是接口或抽象类,细节指的就是实现类,那么依赖倒置再Java中的表现就是:

  • 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生
  • 接口或抽象类不依赖于实现细节
  • 实现类依赖接口或抽象类

更加精简的定义:“面向接口编程 OOD”,依赖倒置原则同通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间松耦合,在项目中:

  • 每个类尽量都有接口或抽象类,或者抽象类和接口都具备
  • 变量的表明类型尽量是接口或抽象类
  • 任何类都不应该从具体类派生
4.接口隔离原则(ISP)

​Java中的接口分为两种:

  1. 实例接口,Java中声明一个类,然后用new关键字产生一个实例,它是对一个类型事物的描述,这是一种接口。比如 Person zhangSan = new Person(), 这里要求Preson这个类要遵循 ISP 这个原则
  2. 类接口,Java中interface关键字定义的接口

而隔离的两种定义:

  • 客户端不应该依赖它不需要的接口
  • 类间的依赖关系应该建立在最小的接口上

总的来说要求

  • 接口尽量细化,同时接口中的方法尽量少
    • 看似与SRP原则相同,但是两者的关注点并不一样,SRP 侧重的是职责,是根据业务逻辑上的划分,而ISP要求接口中的方法尽量少。比如一个职能接口可能包含了10方法,外部通过文档约束“不使用的方法不要访问”,按照SRP是可以的,但是按照ISP 是不允许的,外部系统需要什么才给什么,接口需要尽可能的细化。
5.迪米特法则(LOD

​ 迪米特法则也称为最少知识原则,描述的是:一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的这么多public方法,我就调用这么多,其他的我不关心。就像包工头从甲方接到了一个任务,甲方只会找包工头问任务进度,不管包工头下一群员工怎么干活。

​ 相对而言一个类公开的public属性或方法越多,修改时涉及的面也越大,变更引起的风险扩散也越大,因此设计的时候需要反复衡量:是否还可以再减少public方法和属性,是否可以修改为private、package-parivate、protected等访问权限,是否可以加上final关键字等。可以坚持一个原则: 如果一个方法放在本类中,即不增加类间关系,也对本类不产生负面影响,就放置再本类中

6.开闭原则(OCP)

​ 定义:Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. —> 一个软件实体如类、模块和函数应该对扩展开发,对修改关闭。意思我们应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化,虽是这么说但是难度真大

最后简单的辅助记忆小手段:solid (s-SRP、o-OCP、l-LSP/LOD、i-ISP、d-DIP)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值