Java-设计模式【之】 有道有术(设计原则,代码示例,看完必会)
名词解析
- 高内聚,低耦合、可读性、可扩展性、可维护性、代码重用性
- 高内聚,低耦合
类与类之间必然会存在交互,当存在互相依赖和调用的时候,尽量满足 高内聚 :(类、功能)自身各种属性与方法的紧密联系 低耦合 :(类、功能)与外部交互时的少量联系,只通过几个方法函数,进行交互
- 可读性
编写代码遵守一定规范,容易阅读与理解。 比如:不要使用过长的链式调用,要添加必要的注释信息,遵守Java标识符命名规范,或者公司内部统一开发规范
- 可扩展性
对于新增的功能,不会影响到已经存在的功能,并且容易添加 比如:新增一个特殊的解析JSON的独立工具类,只需要实现已经存在的JSON接口,并新增一个特殊方法。代码中只需要修改引用类型即可。
- 代码重用性
同一功能的代码,不需要重新编写,只需要稍加改动即可 比如:封装工具方法,或者打成jar包,引入使用
1.单一职责
- 单一职责
(功能模块、类、接口、函数)创建的目的性要明确清晰,只是为了实现某一种 或 某一类的职责。
- 个人理解
1.单一职责的类,只为处理职责以内的问题,代码相对会容易理解 2.降低变更风险,提高可维护性 3.虽然是职责单一,但是未必只能有一个类。也可以是方法层面的单一职责,也可以是多个类实现一个职责。
2.接口隔离
- 接口隔离
实现特定功能所需的多种职责接口,应按照职责划分,各个接口之间应该独立存在,(尽量)不要有关联关系
- 个人理解
对单一职责的再次强调,接口的设计,需要合理的规划与拆分,满足低耦合标准。
3.依赖倒置(面向接口编程)
- 依赖倒置原则
1.依赖倒置的原则核心就是 面向接口编程 2.低层模块依赖高层模块 3.细节依赖抽象
- 个人理解
对于一个功能的实现,细节过于繁琐,抽象后会结构清晰 按照抽象的结构 以抽象为基础,实现后的代码 容易理解、结构清晰,
- 如:画出UML类图,指定接口名与内部应具备的函数方法,指出依赖关系,把代码实现分发给其他人去完成
- java中:抽象指的是接口(interface)或抽象类(abstract),细节就是具体的实现类
- 注意
1.低层模块,尽量实现抽象类或接口,这样程序稳定性更好. 2.变量,尽量使用抽象类或接口最为类型声明, 利于程序扩展
4.里氏替换
- 里氏替换原则
子类继承父类后,尽量不要重写父类的方法。 推荐使用 聚合、组合、引用,来达到目的。
- 理解
通常在继承以后,重写父类的方法完成新的功能 这样写起来简单,但复用性会比较差,会增加代码的耦合性。
- 如果:子类继承父类时,如果存在一个父类,多个子类
1.变量引用:子类引用了父类定义的变量,父类修改变量后,全部子类将出现变更 2.方法引用:子类引用了父类定义的方法,父类修改方法后,全部子类将出现变更 3.变量重写:子类重写父类变量,多个子类间,同一变量会不相同 4.方法重写:子类重写父类方法,多个子类间,同一方法会不相同
- 推荐使用 聚合、组合、引用,来达到目的。
5.开闭原则
- 开闭原则(ocp原则)
- 用抽象构建框架结构,用实现扩展细节(面向接口编程)
- 增加新功能的时候,尽量不修改代码,或者尽可能少修改代码
- 开:对扩展开放。(新增功能、代码、函数)
- 闭:对修改关闭。(改动旧功能、代码、函数)
- 理解
本质上还是强调,面向接口编程,当考虑到扩展的情况,首先抽象出功能接口 当真的出现扩展时,新写一个实现类就可以了,源代码不需要改变
6.迪米特(好朋友原则)
- 迪米特原则(最少知道原则)
1.类与类之间做到,最少的交互 2.逻辑封装在类的内部,对外只提供简单的方法 3.迪米特法则的核心是降低类之间的耦合 4.迪米特法则只是要求降低,并不是要求完全没有依赖关系
- 尽量与直接的朋友通信
一个类,不应该以局部变量的形式出现在其他类中
- 直接朋友:成员变量,方法参数,方法返回值
- 陌生朋友:以局部变量的形式,出现的其他类。
class A {
}
class B {
}
public class Start {
A a = new A();
B b = new B();
public A test(A paramA) {
A _a_ = new A();
return paramA;
}
public B test(B paramB) {
B _b_ = new B();
return paramB;
}
}
7.合成复用
- 合成复用原则
功能设计与实现的过程中,必然产生联系的类与类(对象与对象) 之间。 尽量使用 合成/聚合的方式,而不是使用继承。
8.精华:代码示例
解析
- 下面一段代码是为了满足 1~7 ,所写的一段代码,粘贴运行即可
- 代码描述的是,各种
木材 、各种 厂商 、生产不同家具 - 要求:尽量满足 解耦与可扩展,并描述代码所体现的思想
-
代码满足条件解析 -
1.单一职责:其中,制造接口与刷漆接口已经分离。因为生产椅子需要刷漆,生产桌子不需要刷漆。 -
2.接口隔离:其中,制造方法与刷漆方法,抽象到了两个接口中,实现接口最小化,满足隔离条件。 -
3.依赖倒置:已经满足,面向接口编程,且如果需要扩展,只需要创建一个生产厂商类即可,不会变动旧代码。 -
4.里氏替换:使用的是接口,而不是继承木材类,降低继承带来的耦合增强。 -
5.开闭原则:新增生产厂商生产家具,只需要创建一个生产厂商类即可,不会变动旧代码,满足对扩展开放,对修改关闭。 -
6.迪米特原则:其中,木材类是通过参数传递,而不是内部new出来,满足 好朋友原则。 -
7.合成复用:木材类对象作为成员变量,通过构造函数参数传递,而不是使用继承木材类 后实现,满足合成复用
interface 制造接口 {
void 制造();
}
interface 刷漆接口 {
void 刷漆();
}
class 木材类 {
public String name;
public 木材类(String name) {
this.name = name;
System.out.println("当前木材:" + name);
}
}
class 桌子厂商 implements 制造接口 {
木材类 mc;
public 桌子厂商(木材类 mc) {
this.mc = mc;
}
@Override
public void 制造() {
System.out.println("使用 " + mc.name + " 制造了一张桌子");
System.out.println();
}
}
class 椅子厂商 implements 制造接口, 刷漆接口 {
木材类 mc;
public 椅子厂商(木材类 mc) {
this.mc = mc;
}
@Override
public void 制造() {
System.out.println("使用 " + mc.name + " 制造了一把椅子");
this.刷漆();
}
@Override
public void 刷漆() {
System.out.println("椅子材料 " + mc.name + " ,状态:刷漆完成");
System.out.println();
}
}
public class 测试类 {
public static void main(String[] args) {
木材类 ys = new 木材类("杨树");
桌子厂商 zz = new 桌子厂商(ys);
zz.制造();
木材类 ss = new 木材类("松树");
椅子厂商 yz = new 椅子厂商(ss);
yz.制造();
}
}
《上一篇:Java-UML类图》
《下一篇:唯一的路就是正确的路 (单例模式)》
《目录:Java基础》
《幕》
- 留白----《老吉》
- ~ 今 ~ ? ~ ?????????? ?????????? ???????
|