Java设计模式(23种)
UML的定义
结构式图形
- 静态图(类图,对象图,包图)
- Class Diagram:用于表示类、接口、实例等之间相互的静态关系
- 虽然名字叫类图,但类图中并不只有类
- 实现图(组件图,部署图)
- 剖面图
- 复合结构图
行为式图形
- 活动图
- 状态图
- 用例图
记忆技巧-箭头方向
- 定义子类时需要通过extends关键字指定父类
- 子类一定是知道父类定义的,但父类并不知道子类的定义
- 只有知道对方信息时才能指向对方
- 所以箭头方向是从子类指向父类
记忆技巧-实线-继承 | 虚线-实现
◆空心三角箭头:继承或实现
◆实线继承,isa关系,扩展目的,不虚很结实
◆虚线-实现,虚线代表”虚”无实体
记忆技巧-实线关联 | 虚线-依赖
◆实线关联关系:关系稳定,实打实的关系,铁哥们
◆表示一个类对象和另一个类对象有关联
◆通常是一个类中有另一个类对象做为属性
记忆技巧空心菱形-聚合|实心菱形-组合
◆菱形就是一个盛东西的器皿(例如盘子)
◆聚合:代表空器血里可以放很多相同东西,聚在一起(箭头方向所指的类)
◆组合:代表满器皿里已经有实体结构的存在,生死与共
记忆技巧-空心菱形聚合
◆整体和局部的关系,两者有着独立的生命周期,是has a的关系
◆弱关系
◆消极的词:弱-空
时序图
从上至下: 上:过去 下:未来
类的表示
- 抽象类(斜体)
- 接口 中间加字母
- 正常类
设计原则
设计原则讲究一个度,原则,平衡,不能麻木套原则。
程序的机制追求
- 可维护性Maintainability
- 修改功能,需要改动的地方越少,可维护性就越好
- 可复用性Reusability
- 代码可以被以后重复使用
- 写出自己总结的类库
- 可扩展性Extensibility/ Scalability
- 添加功能无需修改原来代码
- 灵活性flexibility / mobility / adaptability
- 代码接口可以灵活调用
开闭原则(Open Closed Principle,OCP)
◆定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
◆用抽象构建框架,用实现扩展细节
◆优点:提高软件系统的可复用性及可维护性–弹性制 -->面向抽象编程
实现开闭原则的方法:面向抽象原则
- 让类依赖于固定的抽象
实现方法
– (java利用接口编程进行解耦之类继承父类,进行业务之间的强转,达到扩展目的)
public static void main(String[] args) {
ICourse iCourse = new JavaDiscountCourse(96, "Java从零到企业级电商开发", 348d);
JavaDiscountCourse javaCourse = (JavaDiscountCourse) iCourse;
System.out.println("课程ID:" + javaCourse.getId() + " 课程名称:" + javaCourse.getName() + " 课程原价:" + javaCourse.getPrice() + " 课程折后价格:" + javaCourse.getDiscountPrice() + "元");
}
public class JavaDiscountCourse extends JavaCourse {
//使用父类的构造器进行扩展
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
//扩展字段
public Double getDiscountPrice(){
return super.getPrice()*0.8;
}
}
小总结
业务扩展方法,通过接口编程,进行业务的扩展极大程度解除耦合。
依赖倒置原则(Dependence Inversion Principle,DIP)
定义:
高层模块不应该依赖低层模块,二者都应该依赖其抽象
◆抽象不应该依赖细节;细节应该依赖抽象
◆针对接口编程,不要针对实现编程
优点:
可以减少类间的耦合性、提高系统稳定性,提高代码可读性
和可维护性,可降低修改程序所造成的风险
单一职责原则(Single Responsibility Principle,SRP)
定义:
一个类不要设计的太大,别太累,负责单一的职责。
-
Person
-
PersonManager
-
高内聚,低耦合。
优点:
降低类的复杂度、提高类的可读性,提高系统的可维护性、降低变更引起的风险
接口隔离原则(Interface Segregation Principle,ISP)
定义:
用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口
马士兵:
每一个接口应该承担独立的角色,不干不该自己干的事儿
–Flyable Runnable不该合二为一
–避免子类实现不需要实现的方法
–需要对客户提供接口的时候,只需要暴露最小的接口
◆一个类对一个类的依赖应该建立在最小的接口上
◆建立单-接口,不要建立庞大臃肿的接口
◆尽量细化接口,接口中的方法尽量少
◆注意适度原则, 一定要适度
- 过大过小都不好
优点:
符合我们常说的高内聚低耦合的设计思想从而使得类具有很好的可读性、可扩展性和可维护性。
什么是高内聚低耦合?
在适当的接口中定义合适的接口,方法不要过多要适度。
迪米特原则
定义:
一个对象应该对其他对象保持最少的了解。又叫最少知道原则
尽量降低类与类之间的耦合
◆优点:
降低类之间的耦合、
迪米特原则
定义:
强调只和朋友交流,不和陌生人说话
降低类之间对的耦合
- 减少类之间的引用
朋友:
出现在成员变量、方法的输入、输出参数中的类称为成员朋友类,
而出现在方法体内部的类不属于朋友类。
里氏替换原则
不应该覆盖父类的方法,而是在原来的基础上进行扩展。
子类的行为需要和父类标志一致。
重载的时候,入参比父类范围大。 避免调用父类方法
子类实现(抽象方法)父类方法时,返回值必须更严格,或者等同。
马士兵:
●Law of Demeter
.尽量不要和陌生人说话
.在迪米特法则中,对于一个对象,非陌生人包括以下几类:
当前对象本身(this);
以参数形式传入到当前对象方法中的对象;
当前对象的成员对象;
如果当前对象的成员对象是一一个集合, 那么集合中的元素也都是朋友;
当前对象所创建的对象。
●和其他类的耦合度变低
定义:
如果对每一个类型为T1的对象o1,都有类型为T2的对象o2 ,
使得以T1定义的所有程序P在所有的对象o1都替换成o2时,
程序P的行为没有发生变化,那么类型T2是类型T1的子类型。
定义扩展:
一个软件实体如果适用一个父类的话,那一定适用于其子类,
所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够
替换父类对象,而程序逻辑不变。
引申意义:
子类可以扩展父类的功能,但不能改变父类原有的功能。
含义1 :子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
含义2 :子类中可以增加自己特有的方法。
含义3 :当子类的方法重载父类的方法时,方法的前置条件
(即方法的输入/入参)要比父类方法的输入参数更宽松。(重点)
含义4 :当子类的方法实现父类的方法时(重写/重载或实现抽象方法)
方法的后置条件(即方法的输出/返回值)要比父类更严格或相等。
优点:
优点1:约束继承泛滥,开闭原则的一种体现。
优点2 :加强程序的健壮性,同时变更时也可以做到非常好的兼容性
提高程序的维护性、扩展性。降低需求变更时引入的风险。
合成(组合)/聚合复用原则
尽量使用聚合,不要使用继承,增加不必要的耦合。
定义:
尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的
聚合has- A和组合contains-A
优点:
可以使系统更加灵活,降低类与类之!间的耦合度,一个类的变化对其他类造成的影响相对较少.
使用场景:
简单工厂
使用场景
- 工厂类负责创建的对象比较少
- 客户端(应用层)只知道传入工厂类的参数
对于如何创建对象(逻辑)不关心
优点:
- 只需要传入-个正确的参数,就可以获取你所需要的对象而无须知道其创建细节
- 客户端(应用层)只知道传入工厂类的参数对于如何创建对象(逻辑)不关心
- 只需要传入-个正确的参数,就可以获取你所需要的对象而无须知道其创建细节
缺点:
- 工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则
总结:–六大原则
- OCP: 总纲,对扩展开饭,对修改关闭
- SRP:类的职责要单一
- LSP之类可以透明替代父类
- DIO:面向接口编程
- ISP:接口的职责要单一
- LoD:降低耦合
装饰者模式
定义:
在不改变原有对象的基础之上,将功能附加到对象 上
提供了比继承更有弹性的替代方案(扩展原有对象功能)
类型:
–结构型
使用场景:
- 扩展一个类的功能或给一个类添加附加职责
- 动态的给一个对象添加功能,这些功能可以再动态的撤销
优点:
- 继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象
扩展功能 (优点) - 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
- 符合开闭原则
缺点:
看起来类之间非常像。不容易排查错误。
- 会出现更多的代码,更多的类,增加程序复杂性
- 动态装饰时,多层装饰时会更复杂