【不就是java设计模式吗】设计模式七大原则,用代码对比方式,化抽象为具体,实打实的教会你

简介: 【不就是java设计模式吗】设计模式七大原则,用代码对比方式,化抽象为具体,实打实的教会你

一、为什么要学习设计模式?

在编写软件的过程中,设计模式是为了让软件具有更好的以下优点:


代码重用性(相同功能的代码不用多次编写)

可读性(编程规范性,便于其他程序员的阅读和理解)

可扩展性(当需要增加新的功能时,非常的方便)

可靠性(当增加新的功能后,对原来的功能没有影响)

使程序呈现高内聚、低耦合的特性

二、常用的七大原则

单一职责原则

接口隔离原则

依赖倒转原则

里氏替换原则

开闭原则

迪米特法则

合成复用原则

三、单一职责原则

1、基本介绍

对类来说,一个类应该只负责一项职责。如果类A负责两个不同的职责:职责1、职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A分解为A1、A2。


这么说有点抽象,下面用代码来演示一下,化抽象为具体。


2、代码对比

代码一:


public class class01 {
    public static void main(String[] args) {
        Vehicle1 vehicle = new Vehicle1();
        vehicle.run("汽车");
        vehicle.run("飞机");
        vehicle.run("轮船");
    }
}
class Vehicle1 {
    public void run(String vehicle){
        System.out.println(vehicle + "在高速上行驶");
    }
}


通过代码一可以看出,这样设计的结果是:飞机和轮船也是在高速上行驶,违反了单一职责原则,这显然是错误的。接下来看看代码二,与其对比一下。


代码二:


public class class02 {
    public static void main(String[] args) {
        VehicleRoad road = new VehicleRoad();
        road.run("汽车");
        VehicleWater water = new VehicleWater();
        water.run("轮船");
    }
}
class VehicleRoad {
    public void run(String vehicle) {
        System.out.println(vehicle + "在高速上行驶");
    }
}
class VehicleWater {
    public void run(String vehicle) {
        System.out.println(vehicle + "在水中行驶");
    }
}



通过代码二,我们根据交通工具运行方法不同,分解成不同的类,解决了代码一的问题。但是有一个问题就是,这样很浪费资源,改动很大。貌似不太完美,接下来看看代码三


代码三:


public class class03 {
    public static void main(String[] args) {
        Vehicle2 vehicle = new Vehicle2();
        vehicle.runRoad("汽车");
        vehicle.runWater("轮船");
    }
}
class Vehicle2{
    public void runRoad(String vehicle){
        System.out.println(vehicle + "在高速上行驶");
    }
    public void runWater(String vehicle){
        System.out.println(vehicle + "在水中行驶");
    }
}


代码三通过修改方法,与代码二比较,对原来的类没有做很大的修改,只是增加方法。这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然是遵守单一职责原则。


3、注意事项和使用细节

要降低类的复杂度,一个类只负责一项职责

确保提高类的可读性,可维护性

降低变更引起的风险

通常情况下,我们应当遵守单一职责原则,只有逻辑 足够简单,才可以在代码级别违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则

四、接口隔离原则

1、基本介绍

客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。


先看看一张图:

image.png

代码一:


public class class01 {
    public static void main(String[] args) {
        A a = new A();
        a.method1(new B());
        C c = new C();
        c.method2(new D());
    }
}
interface Interface1{
    void opertion1();
    void opertion2();
    void opertion3();
    void opertion4();
    void opertion5();
}
class B implements Interface1{
    public void opertion1() {
        System.out.println("B 实现了 operation1");
    }
    public void opertion2() {
        System.out.println("B 实现了 operation2");
    }
    public void opertion3() {
        System.out.println("B 实现了 operation3");
    }
    public void opertion4() {
        System.out.println("B 实现了 operation4");
    }
    public void opertion5() {
        System.out.println("B 实现了 operation5");
    }
}
class D implements Interface1{
    public void opertion1() {
        System.out.println("D 实现了 operation1");
    }
    public void opertion2() {
        System.out.println("D 实现了 operation2");
    }
    public void opertion3() {
        System.out.println("D 实现了 operation3");
    }
    public void opertion4() {
        System.out.println("D 实现了 operation4");
    }
    public void opertion5() {
        System.out.println("D 实现了 operation5");
    }
}
class A { // A 类 通过接口Interface1 依赖 B类,但只使用1、2、3方法
    public void method1(Interface1 interface1){
        interface1.opertion1();
    }
    public void method2(Interface1 interface1){
        interface1.opertion2();
    }
    public void method3(Interface1 interface1){
        interface1.opertion3();
    }
}
class C { // C 类 通过接口Interface1 依赖 D类,但只使用1、4、5方法
    public void method1(Interface1 interface1){
        interface1.opertion1();
    }
    public void method2(Interface1 interface1){
        interface1.opertion4();
    }
    public void method3(Interface1 interface1){
        interface1.opertion5();
    }
}



代码一中,类A通过接口Interface1 依赖类B,类C通过接口Interface1 依赖类D,因为接口Interface1 对于类A 和类C来说不是最小接口,所以要想实现图片的功能,需要实现接口的所有方法,违反了接口隔离原则! 接下来看看代码二,与其对比一下。


代码二:


public class class02 {
    public static void main(String[] args) {
        AA aa = new AA();
        aa.method1(new BB());
        CC cc = new CC();
        cc.method1(new DD());
    }
}
interface Interface2{
    void opertion1();
}
interface Interface3{
    void opertion2();
    void opertion3();
}
interface Interface4{
    void opertion4();
    void opertion5();
}
class BB implements Interface2,Interface3{
    public void opertion1() {
        System.out.println("BB 实现了operation1");
    }
    public void opertion2() {
        System.out.println("BB 实现了operation2");
    }
    public void opertion3() {
        System.out.println("BB 实现了operation3");
    }
}
class DD implements Interface2,Interface4{
    public void opertion1() {
        System.out.println("DD 实现了operation1");
    }
    public void opertion4() {
        System.out.println("DD 实现了operation4");
    }
    public void opertion5() {
        System.out.println("DD 实现了operation5");
    }
}
class AA {
    public void method1(Interface2 interface2){
        interface2.opertion1();
    }
    public void method2(Interface3 interface3){
        interface3.opertion2();
    }
    public void method3(Interface3 interface3){
        interface3.opertion3();
    }
}
class CC {
    public void method1(Interface2 interface2){
        interface2.opertion1();
    }
    public void method2(Interface4 interface4){
        interface4.opertion4();
    }
    public void method3(Interface4 interface4){
        interface4.opertion5();
    }
}


代码二的UML类图:

image.png


代码二采用了接口隔离原则。根据实际情况,把代码一中的接口Interface1拆分成三个接口,即最小接口。这样就完美的去除了类BB和类DD不用实现他们不需要的方法


相关文章
|
7天前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
|
21天前
|
XML 安全 Java
Java反射机制:解锁代码的无限可能
Java 反射(Reflection)是Java 的特征之一,它允许程序在运行时动态地访问和操作类的信息,包括类的属性、方法和构造函数。 反射机制能够使程序具备更大的灵活性和扩展性
34 5
Java反射机制:解锁代码的无限可能
|
17天前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
48 3
|
23天前
|
存储 安全 Java
系统安全架构的深度解析与实践:Java代码实现
【11月更文挑战第1天】系统安全架构是保护信息系统免受各种威胁和攻击的关键。作为系统架构师,设计一套完善的系统安全架构不仅需要对各种安全威胁有深入理解,还需要熟练掌握各种安全技术和工具。
64 10
|
18天前
|
分布式计算 Java MaxCompute
ODPS MR节点跑graph连通分量计算代码报错java heap space如何解决
任务启动命令:jar -resources odps-graph-connect-family-2.0-SNAPSHOT.jar -classpath ./odps-graph-connect-family-2.0-SNAPSHOT.jar ConnectFamily 若是设置参数该如何设置
|
17天前
|
Java
Java代码解释++i和i++的五个主要区别
本文介绍了前缀递增(++i)和后缀递增(i++)的区别。两者在独立语句中无差异,但在赋值表达式中,i++ 返回原值,++i 返回新值;在复杂表达式中计算顺序不同;在循环中虽结果相同但使用方式有别。最后通过 `Counter` 类模拟了两者的内部实现原理。
Java代码解释++i和i++的五个主要区别
|
24天前
|
搜索推荐 Java 数据库连接
Java|在 IDEA 里自动生成 MyBatis 模板代码
基于 MyBatis 开发的项目,新增数据库表以后,总是需要编写对应的 Entity、Mapper 和 Service 等等 Class 的代码,这些都是重复的工作,我们可以想一些办法来自动生成这些代码。
30 6
|
25天前
|
Java
通过Java代码解释成员变量(实例变量)和局部变量的区别
本文通过一个Java示例,详细解释了成员变量(实例变量)和局部变量的区别。成员变量属于类的一部分,每个对象有独立的副本;局部变量则在方法或代码块内部声明,作用范围仅限于此。示例代码展示了如何在类中声明和使用这两种变量。
|
26天前
|
存储 Java API
优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。
【10月更文挑战第19天】本文介绍了如何优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。内容包括Map的初始化、使用Stream API处理Map、利用merge方法、使用ComputeIfAbsent和ComputeIfPresent,以及Map的默认方法。这些技巧不仅提高了代码的可读性和维护性,还提升了开发效率。
50 3
|
25天前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
40 0
[Java]23种设计模式