设计模式(1) 设计模式理论

首先我个人认为要知道的基本道理是设计模式的理论是相对的,很多时候要根据实际的情况来,从维度,对是否违背进行一个权衡。

基本概念

高内聚:所谓的高内聚,是指相近的功能应该放到同一个类中,不相近的功能不要放到同一个类中。相近的功能往往会被同时修改,放到同一个类中,修改会比较集中,代码容易维护。

低耦合:在代码中,类与类之间的依赖关系简单清晰。即使两个类有依赖关系,一个类的代码改动不会或者很少导致依赖类的代码改动。

可维护性(maintainability):所谓的“维护”无外乎就是修改 bug、修改老的代码、添加新的代码之类的工作。可维护性越好,当然是越容易进行维护,维护不容易对业务造成影响。

可扩展性(extensibility):我个人认为可扩展就是可维护的一个子集,扩展即维护。

灵活性(flexibility): 灵活性,即写出的这段代码,①有预留扩展点容易扩展。②容易被复用。③功能齐全。

可读性(readability):如何评价一段好的代码可读性强?复杂的逻辑被封装的同时,能让人清晰的感觉到你的逻辑,这就是可读性强。

可测试性(testability):可测试性,对于我们开发来说①即单测是否好写,也就是说是否容易达到高覆盖率。②改动了代码原来的单测是否可以有效的覆盖。

SOLID原则

S为单一职责原则(Single Responsibility Principle)缩写为 SRP。
这个原则的英文描述是这样的:
A class or module should have a single reponsibility。
一个类或者模块只负责完成一个职责(或者功能)。

好处:
1.很明显接口职责单一,会让该接口,高内聚,低藕合。
2.接口的粒度小,方法更容易复用。
3.类的职责单一在面向类的属性上,不同的领域模型属性不应该出现在同一个类里面,这样可以从根本上减少与别的类属性直接的关联性。

I为接口隔离原则
它的英文描述是:
upon interfaces that they do not use。
客户端不应该强迫依赖它不需要的接口。

I其实跟S很相似,接口隔离原则强调的是我们在实现接口时,不要强行实现不应该实现的接口,从而控制住类的粒度。总的来说接口隔离主要是面向调用者的,不应该给调用者暴露不应该让他在这个接口中调用的API。

O为开闭原则(Open Closed Principle),简写为 OCP。
它的英文描述是:
software entities (modules, classes, functions, etc.) should be open for extension ,but closed for modification。
软件实体(模块、类、方法等)应该“对扩展开放、对修改关闭”。

基本上,我们的设计模式理念就是为开闭原则服务,何为对修改关闭?这我觉得应该是大部分人迷茫的地方,首先如果要对功能进行扩展,修改代码是肯定的,但修改在哪里这就又是一种讲究,对修改关闭,我们关注的是在哪个维度的关闭,比如我通过实现某个接口,使现有功能进行了扩展,没有对原有的方法进行修改,那么我这就是对方法进行了开闭原则。

好处:
1.可维护行好,不容易影响业务整体流程。
2.测试性好,只需要在原来有的架子中增加自己的新功能测试就行了。

L为里式替换原则(Liskov Substitution Principle),缩写为 LSP。
它的英文描述是:
Functions that use pointers of references to base classes must be able to use objects of derived classes without knowing it。
子类对象(object of subtype/derived class)能够替换程序(program)中父类对象(object of base/parent class)出现的任何地方,并且保证原来程序的逻辑行为(behavior)不变及正确性不被破坏。

简单来说我们在实现接口或者父类时要满足:
1.子类不能违背父类声明要实现的功能。
2.子类违背父类注释中所罗列的任何特殊说明。
3.子类不能违背父类对输入、输出、异常的约定。

好处:增强可维护性,如果通过重写父类的方法,修改父类方法逻辑,我们要关注仅仅是父类的逻辑处理,比如是否复合原义,对某些情况的处理,是抛异常,还是返回。

D为依赖反转原则(Dependency Inversion Principle),缩写为 DIP。
High-level modules shouldn’t depend on low-level modules. Both modules
should depend on abstractions. In addition, abstractions shouldn’t depend on
details. Details depend on abstractions

高层模块(high-level modules)不要直接依赖低层模块(low-level)。高层模块和低层模块应该通过抽象(abstractions)来互相依赖。除此之外,抽象(abstractions)不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions)。

总的来说就是面向接口编程,我们调用一组API时,应该跟他的接口依赖,而不是跟实际的实现类进行依赖。

迪米特法则

迪米特法则(LOD)Law of Demeter,Each unit should have only limited knowledge about other units: only units “closely” related to the current unit. Or: Each unit should only talk to its friends; Don’t talk to strangers.
每个模块(unit)只应该了解那些与它关系密切的模块(units: only units “closely” related to the current unit)的有限知识(knowledge)。或者说,每个模块只和自己的朋友“说话”(talk),不和陌生人“说话”(talk)。
不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。

KISS原则

Keep It Simple and Stupid。尽量保持简单。
在代码的功能实现的前提下,尽可能保证可读性。很多时候同一个功能有多种实现的方式,这时候要尽量选择可读性好的实现方式。当然,这需要在效率和可读性中做出权衡,有些时候有些功能为了确保效率不得不使用一些算法来保证效率。

DRY原则

Don’t Repeat Yourself。不要重复你自己。
什么才算是重复要搞清楚。
1、两个功能处理逻辑一样。
比如校验账号和密码格式目前方式是一样的。
虽然他们此时是一样,但是代表以后还是一样,这种情况我们应该写出两个校验的方法,而不是用一个方法同时校验他们两个,功能是不一样的,即使里面逻辑一样。这违背了单一职责原则和接口隔离原则。
2、功能语义重复。
比如在工具类里面有多个DateUtil,这样从某种意义来说不便于管理,比如突然发现一个方法addDay()有bug,但是不知道别的DateUtil是否有这个方法;有,但是是否有这个bug;是否被调用过;如果在一个类中突然有一个DateUtil没有这个功能但是另一个有导致全类名显示的情况。这种情况,在微服务的情况下,可能无法避免,唯一要做的就是做好自己,在想实现某种感觉比较常用的逻辑时,先看看有没有,有的话如果有多个这种工具类认定一个比较全的类去使用,对于自己来说以后就用这一个。
3、代码执行重复
比如判空,在上游有了,下游仍然有,这种得我个人认为,对于一个敏捷开发者来说,可以重复,以防报空指针异常,对于目前的计算机效率来说,我认为这是可以接收的。我们应该要注意的重复就是读库,RPC调用等较为影响时间的重复语句。
4、BO、DTO、PO重复
类里面的属性完全一样。但这不算重复,任何事物在不同的维度下看待是不一样的,在3层架构中,我关注的是当前层的情况,别的层,即使一样,但职责不一样,PO处理数据库,BO处理业务、DTO处理请求。就好比我在Facade层校验了mobile这个参数,但是Service里面又校验了mobile这个参数,这其实也不算重复,Service毕竟是可以被别的Facade和Service调用的,你需要这个mobile的参数校验,因为你不知道他们在调用之前是否进行了这个mobile的参数的校验。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值