最新动态
Java 6大设计原则28大设计模式
2024-11-28 03:46  浏览:99

1. 单一职责原则

单一职责原则的英文名称是 Single Responsibility Principle ,简称是SRP(There should never be more than one reason for a class to change.
见名知意,充斥着满满的争议,需求的更替,版本的迭代,场景的复杂,种种都能导致这个被破坏,但是把出发点是好的,单一意味着简单,简单意味着易懂,而后易维护、节省人力、成本、增加稳定性;但是场景复杂时就类就多了,em...;仁者见仁智者见智,不展开讲了

2. 里氏替换原则

里氏替换原则 Liskov Substitution Principle LSP
定义1
If for each object o1 of type S there is an object o2 of
type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is
substituted for o2 then S is a subtype of T. (如果对每一个类型为 S 的对象 o1 ,都有类型为 T 的对
o2 ,使得以 T 定义的所有程序 P 在所有的对象 o1 都代换成 o2 ,程序 P 的行为没有发生变
,那么类型 S 是类型 T 的子类型。
定义2
Functions that use pointers or references to base classes must be able to use
objects of derived classes without knowing it. (所有引用基类的地方必须能透明地使用其子类的
对象。
说的就是Java中父子关系(继承、实现,父类出现的地方,可替换成子类
原则上相当于制定了契约
正例不举了,我举个反例吧
如果其他程序调用时,不能通过父类或者接口,而必须使用子类时,则说明类的设计已经违背了LSP原则
 
    

Java 6大设计原则28大设计模式

3. 依赖倒置原则

依赖倒置原则 Dependence Inversion Principle,DIP
High level modules should not depend upon low level modules.Both should depend upon
abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.
  • 模块间的依赖通过抽象发生(接口或抽象类
  • 接口或抽象类不依赖于实现类
  • 实现类依赖接口或抽象类
简而言之就是解耦

4. 接口隔离原则

Interface Segregation Principle

  • Clients should not be forced to depend upon interfaces that they don't use. (客户端不应该依
    赖它不需要的接口。
  • The dependency of one class to another one should depend on the smallest possible interface. (类间的依赖关系应该建立在最小的接口上。
简而言之,用什么依赖什么
所以对接口就要求
  • 接口职能单一,服务定制,设计有度
  • 接口要高内聚,减少交互

5. 迪米特法则

迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP
只通过接口协定交互,其他一概不管;only talk to your immediate friends(只与直接的朋友沟通。
是自己的逻辑就是自己的逻辑,不是自己的就不是自己的

6. 开闭原则

Open Closed Principle
Software entities like classes,modules and functions should be open for extension but closed for
modifications. (一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
开闭原则个人粗浅的见解是一个法典,像一种理想化,一种指导方针;我们需要通过抽象约束、规范制度、需求预见等使程序在时间推移的过程中一直在做扩展和增强,减少已有的抽象的修改(例如接口制定了,以后都不用再修改,这个肯定是我们最希望的;我们需要朝这个方向去努力,拥抱变化的同时,越少打破这个原则

1. 单例模式

最简单常用的模式,不展开了

 

2. 工厂方法模式

Define an interface for creating an object,but let subclasses decide which class to
instantiate.Factory Method lets a class defer instantiation to subclasses. (定义一个用于创建对象的
接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
优点
1.  良好的封装性,代码结构清晰
2. 良好的扩展性(横向扩展,例如例子中需要新增一种食物
3. 解耦,散落到各处的类似的初始化逻辑可以被封装,不用重复写,也提高维护性
应用
1. 可简化成 简单工厂模式 用静态方法代替工厂类
2. 升级成多工厂
3. 单例模式的替代品
4. 延迟初始化
 

3. 抽象工厂模式

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们 的具体类。

优点
1. 抽象封装
2. 分类约束
缺陷
1. 子工厂扩展受限

 

4. 模板方法模式

对于业务模型的业务动作模板化;基本方法在子类中实现,模板方法在父类中调度

优点
1. 封装固定部分,扩展可变部分
2. 公共代码提取,统一行为控制
缺陷
1. 行为流程固化(之前是抽象的是一个动作;现在是抽象了动作和动作的顺序
2. 复杂场景新手阅读不适(串联逻辑时,一下到子类,一下到父类,绕晕
 

5. 建造者模式

建造者模式Builder Pattern)也叫做生成器模式

Separate the construction of a complex object from its representation so that the same
construction process can create different representations. (将一个复杂对象的构建与它的表示分
,使得同样的构建过程可以创建不同的表示。
优点
良好的封装性和抽象
易于扩展
和工厂模式类似都是在创建类实例,但是不同的是,建造者开放了一部分流程给外部定制化
 
代理模式(Proxy Pattern
Provide a surrogate or placeholder for another object to control access to it. (为其他对象提供
一种代理以控制对这个对象的访问。
优点
  • 高扩展性,不侵入实现层的源码
  • 职能清晰

缺点

  • 代理在实际项目使用过程中,还是不要下放给所有人,实际经验中,AOP的随意使用,经常造成各种问题,特殊场景下的报错、代码可读性降低(大项目中,新人不知道哪里把数据修改了,代码不易理解,修改引入缺陷,测试不好覆盖场景
 
 

Java中有JDK动态代理和cglib动态代理,可自行研究;动态代理是非常常见和使用的设计模式,对于业务前后统一的处理都可使用此模式;也叫AOP(Aspect Oriented Programming面向切面编程,还有一些名词:切面 Aspect,切入点 JoinPoint,通知 Advice,织入 Weave;概念一大堆,大家还是要从实际场景去考虑我们引入代理到底带来了什么,失去什么,是否合适当前的场景;从个人浅显的工作经验上来看,AOP下放给开发在业务中使用时,经常是弊大于利,谈虎色变

原型模式(Prototype Pattern
Specify the kinds of objects to create using a prototypical instance,and create new objects by
copying this prototype. (用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对
象。
原型模式的核心是一个 clone 方法,通过该方法进行对象的拷贝 Java 提供了一个Cloneable 接口来标示这个对象是可拷贝的
优点:
  • 对于构造函数消耗的性能非常多且实例化的内容是一致的对象能够大幅提高性能
  • 双刃剑:逃避构造函数约束(成也萧何,败也萧何,千万注意此点对业务的影响

缺点

  • 仅深拷贝本对象(属性如果是对象则为浅拷贝
  • clone和final一山不容二虎,成员变量加final后直接编译报错
 
 

Define an object that encapsulates how a set of objects
interact.Mediator promotes loose coupling by keeping objects from referring to each other
explicitly,and it lets you vary their interaction independently. (用一个中介对象封装一系列的对象
交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它
们之间的交互。
优点
减少类间关系,从一对多编程一对一
缺点
中介类肿胀
例如MVC的Controller层就属于中介者模式
命令模式是一个高内聚的模式
Encapsulate a request as an object,thereby
letting you parameterize clients with different requests,queue or log requests,and support undoable operations.(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
优点
类间解耦
可扩展性
缺点
Command子类会非常多,这个类非肿胀
 
 
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to
handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
优点
解耦(请求和处理分开
缺点
“太解耦”,链路太长时,性能差且不好阅读和排查问题
装饰模式 Decorator Pattern
优点
  • 装饰类和被装饰类可以独立发展,而不会相互耦合。
  • 装饰模式是继承关系的一个替代方案
  • 动态扩展类的功能

缺点

  • 不要套太多,套娃太深,复杂度太高,排查和理解耗时
 
策略模式(Strategy Pattern
Define a family of algorithms,encapsulate each one,and make them interchangeable. (定义一组
算法,将每个算法都封装起来,并且使它们之间可以互换。
优点
  • 策略自由切换,方便横向扩展
  • 避免多重条件判断

缺点

  • 策略类数量多时,需要有诸葛亮一样的人来运筹帷幄,复用性也低
  • 所有策略都得对外暴露
 
 
适配器模式 Adapter Pattern
Convert the interface of a class into another interface clients expect.Adapter lets classes work
together that couldn't otherwise because of incompatible interfaces. (将一个类的接口变换成客户
端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工
作。
适配器模式又叫做变压器模式,也叫做包装模式 Wrapper ,但是包装模式可不止一
优点
  • 适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定 他们就成
  • 降低了类的存在感,简化使用
  • 提供类的复用和灵活性

缺点

  • 个人人为也不算缺点吧,项目初期不用考虑这个模式,大多在维护阶段去使用,去适配未知的场景(就像在中国是220的电,做的充电器就按220的做,以后去了未知的地区,再考虑做新的,因为电压,插口大小都是未知的
  • 而且是不符合原有设计的时候才会发生,使用此改造也可能代码比较大的改造量
 
 
迭代器模式(Iterator Pattern )目前已经是一个没落的模式,基本上没人会单独写一个迭
代器
Provide a way to access the elements of an aggregate object sequentially without exposing its
underlying representation. (它提供一种方法访问一个容器对象中各个元素,而又不需暴露该
对象的内部细节。

 
 

Java本身已经提供了很强大的基础API,所以我们基本不需要自己再去写这些

组合模式 (Composite Pattern) 也叫合成模式,有时又叫做部分 -整体模式(Part-Whole,主要是用来描述部分与整体的关系
Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.(将对象组合成树形结构以表示 部分 - 整体 的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
优点
1. 整体部分调用简单
2. 部分增加自由
缺点
1. 部分没有定义,直接使用了实现类(对于面向接口编程的理念是不一致的,与依赖导致原则冲突
使用场景
1. 维护部分和整体的关系,树形菜单、目录结构、组织架构
2. 从一个整体中能独立出去的部分
观察者模式 Observer Pattern)也叫做发布订阅模式(Publish/subscribe ,它是一个在项 目中经常使用的模式
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.(定义对象间一种一对多的依赖关系,使得每 当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
几个主要的组成部分
1. 被观察者
定义被观察者,和主要的动作
2. 观察者
定义观察者收到消息后的动作
3. 具体的被观察者
具体的被观察动作
4. 具体的观察者
具体的观察者动作
 
 

17. 门面模式

门面模式(Facade Pattern)也叫做外观模式,是一种比较常用的封装模式,其定义如 下: Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.(要求一个子系统的外部与其内部的通信必须通 过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。

个人理解门面模式是定义一个统一的规范,不论用什么方式实现,出入的“门面”是固定的,且不暴露门面内部的逻辑

 
 

优点

1. 减少系统的互相依赖

2. 提高门面内部的灵活性和自主性

3. 提高安全性(这个其实也是减少互相依赖带来的好处,减少了代码的侵入

缺点

不符合开闭原则,对修改关闭,对扩展开放,facade类定义好后,出现问题的话,唯一能做的一件事就是修改门面代码,这会影响所有人,所以很多时候,在门面对于一部分场景正确,但对一部分场景错误时,经常会开“后门”,再开一扇门,搞的次数多了,越来越复杂,越来越难以理解,越来越难维护。

门面如果能让优秀的人定义好的话,可以减少低水平开发人员对系统冲击,最差就是将其实现的代码重写,不会对整体造成影响;正如缺点中讲的,也是双刃剑,慎之又慎。

18. 备忘录模式

备忘录模式 Memento Pattern )提供了一种弥补真实世界缺陷的方法,让 后悔药 在程
序的世界中真实可行,其定义如下
Without violating encapsulation,capture and externalize an object's internal state so that the
object can be restored to this state later. (在不破坏封装性的前提下,捕获一个对象的内部状
,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

备忘录就像我们处理数据库事务一样,可以对操作进行回滚

 
 

应用场景

  • 保存恢复数据的场景
  • 数据旁路处理的场景
  • 实际应用过程大多会进行变形,所以其实没有很标准的落地形式,算一种抽象定义

注意点

  • 备忘录的生命周期管理,防止出现内存泄漏,业务脏数据等问题
  • 备忘录创建的性能问题,大量且频繁创建销毁,要考虑内存和CPU的消耗
  • 单纯的整对象备份,可以用Cloneable代替Memento类

大话西游中,周星驰在洞口月光下对着月光宝盒大喊“波若波若蜜”,来回穿梭时光回去救白晶晶,结果频繁操作,旁边的观察者吴孟达一脸懵逼,然后程序不稳定,穿越回了500年前...

18. 访问者模式

访问者模式 Visitor Pattern )是一个相对简单的模式,其定义如下 Represent an
operation to be performed on the elements of an object structure. Visitor lets you define a new
operation without changing the classes of the elements on which it operates. (封装一些作用于某种
数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的
操作。

 
 

优点

  • 符合单一职责原则
  • 可扩展性
  • 灵活性

缺点

  • 违背依赖倒置原则(访问者依赖具体元素,而非抽象元素,很多时候我们在设计开发时会说,不是抽象的,那我抽象不就行了,但除了从代码上是抽象类或者接口,业务上真的是抽象的吗?我们口中的抽象真的是抽象吗
  • 维护麻烦,对于元素增加、修改、删除都是麻烦事

19. 状态模式

Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.(当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。

优点

  • 结构清晰
  • 类符合单一职责和开闭原则,每个状态一个子类

缺点

  • 有很多状态会扩展出很多子类

 
 

状态模式的实际应用场景其实很多,但是现实项目中终究一言难尽,设计模式是好的设计模式,但是最后在落地中,大家口中的shishan代码大部分由于业务状态引起,例如订单状态,各种券的状态等等,业务设计上没有完善的状态机,需求又经常调整场景破坏状态机,状态不由单一字段控制(当A表的a字段=1,B表的b字段=2时需要业务动作x,对于重大项目项目管理和测试又只允许增量修改,导致if写的到处都是,没人知道完整状态机,新人老人避之不及,吐槽程序shishan,这种情况都是大家一起造成的;希望大家在工作中能够遇到完善需求,完善设计,高效扩展,规范开发的项目,能离shishan远一些

未完待续...

-- 有缘登山,寒山不寒

    以上就是本篇文章【Java 6大设计原则28大设计模式】的全部内容了,欢迎阅览 ! 文章地址:http://lanlanwork.gawce.com/quote/9242.html 
     行业      资讯      企业新闻      行情      企业黄页      同类资讯      网站地图      返回首页 阁恬下移动站 http://lanlanwork.gawce.com/mobile/ , 查看更多