七大设计原则

七大设计原则

开闭原则

开闭原则是设计模式中的总原则。

开闭原则就是说:对扩展开放,对修改关闭。

模块应该在不修改原有代码的前提下进行拓展,这就需要使用接口和抽象类来实现预期效果。

开闭原则要求我们尽可能通过拓展来实现变化,尽可能少地改变已有模块,特别是底层模块。

假设我们时4S店汽车销售,类图如图所示

这是一个Java工程,依赖了Lombok

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
</dependency>
public interface Car {
    String getName();
    int getPrice();
}
@AllArgsConstructor
public class BenzCar implements Car {

    private String name;
    private int price;

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public int getPrice() {
        return this.price;
    }

    @Override
    public String toString() {
        return "车名:" + this.getName() + "\t价格:" + this.getPrice() + "万元";
    }
}

模拟一下销售记录

public class OpenCloseTest {

    private final static List<Car> CARS = new ArrayList<>();

    static {
        CARS.add(new BenzCar("梅赛德斯-迈巴赫S级轿车",138));
        CARS.add(new BenzCar("梅赛德斯-AMG S 63 L 4MATIC+", 230));
        CARS.add(new BenzCar("梅赛德斯-奔驰V级", 50));

       
    }


    public static void main(String[] args) {
        System.out.println("4s店售车记录(不含金融服务费):");
        CARS.forEach(System.out::println);
       
    }

}
4s店售车记录(不含金融服务费):
车名:梅赛德斯-迈巴赫S级轿车	价格:138万元
车名:梅赛德斯-AMG S 63 L 4MATIC+	价格:230万元
车名:梅赛德斯-奔驰V级	价格:50万元

如果老板要求添加金融服务费,100w收取5%,50~100w收取2%,50w一下没有。我们要怎么做???

  1. 修改Car接口,新增一个获取金融服务费之后的方法。这样做实现Car接口的所有子类都有改变,不可取。
  2. 修改BenzCar类,这样做就改变了原有的逻辑了,也不可取。
  3. 新增BenzCar子类,重写getPrice方法。推荐使用。
public class FinanceBenzCar extends BenzCar {
    public FinanceBenzCar(String name, int price) {
        super(name, price);
    }

    @Override
    public int getPrice() {
        int selfPrice = super.getPrice();
        if (selfPrice >= 100) {
            // 收取5%的金融服务费
            return selfPrice + selfPrice * 5 / 100;
        } else if (selfPrice >= 50) {
            // 收取2%的金融服务费
            return selfPrice + selfPrice * 2 / 100;
        }
        return selfPrice;
    }

    @Override
    public String toString() {
        return "车名:" + super.getName() + "\t价格:" + this.getPrice() + "万元";
    }
}

测试类修改如下

public class OpenCloseTest {

    private final static List<Car> CARS = new ArrayList<>();
    private final static List<Car> FINANCECARS = new ArrayList<>();

    static {
        CARS.add(new BenzCar("梅赛德斯-迈巴赫S级轿车",138));
        CARS.add(new BenzCar("梅赛德斯-AMG S 63 L 4MATIC+", 230));
        CARS.add(new BenzCar("梅赛德斯-奔驰V级", 50));

        FINANCECARS.add(new FinanceBenzCar("梅赛德斯-迈巴赫S级轿车",138));
        FINANCECARS.add(new FinanceBenzCar("梅赛德斯-AMG S 63 L 4MATIC+", 230));
        FINANCECARS.add(new FinanceBenzCar("梅赛德斯-奔驰V级", 50));
    }


    public static void main(String[] args) {
        System.out.println("4s店售车记录(不含金融服务费):");
        CARS.forEach(System.out::println);
        System.out.println("\n4s店售车记录(包含金融服务费):");
        FINANCECARS.forEach(System.out::println);
    }

}
4s店售车记录(不含金融服务费):
车名:梅赛德斯-迈巴赫S级轿车	价格:138万元
车名:梅赛德斯-AMG S 63 L 4MATIC+	价格:230万元
车名:梅赛德斯-奔驰V级	价格:50万元

4s店售车记录(包含金融服务费):
车名:梅赛德斯-迈巴赫S级轿车	价格:144万元
车名:梅赛德斯-AMG S 63 L 4MATIC+	价格:241万元
车名:梅赛德斯-奔驰V级	价格:51万元

这样做没有修改如何已有类,就实现了逻辑。面向扩展开放,面向修改关闭

开闭原则总结:

  • 提高代码复用性

  • 提高代码可重用性

单一职责原则

简单来说就是保证设计类、接口、方法时功能做到单一,权责明确。单一职责原则指的是一个类且只有一个可改变的原因。

如果模块或类承担的职责过多,就等于这些职责耦合在一起,这样一个模块可能会削弱或抑制其他模块的能力,这样的耦合很脆弱

假设我们修改用户名密码,我们需要为修改密码单独划分一个接口,而不是在修改全部信息中判断是否为null去拼接动态SQL

单一职责原则总结

  • 降低类的复杂性,提高可读性、可扩展性
  • 但是用 “职责” 或 “变化原因” 来衡量接口或类设计得是否优良,但是 “职责” 和 “变化原因” 都是不可度量的,因项目、环境而异;指责划分稍微不当,很容易造成资源浪费,代码量增多,好比微服务时服务边界拆分不清

里氏替换原则

所有使用父类的地方必须能透明的使用其子类对象。

里氏替换原则是开闭原则的实现基础,他告诉我们设计程序的时候尽可能使用父类进行对象的定义和引用,运行时在确定对应的子类。

里氏替换原则总结

  • 提高代码复用性,子类继承父类自然也继承了父类的方法和属性
  • 提高代码扩展性,子类通过实现父类方法进行功能扩展
  • 继承有侵入性,继承就必然有父类的属性和方法
  • 增加代码耦合性。父类方法变更需要考虑子类方法是否变更

依赖倒置原则

程序要依赖于抽象接口,不要依赖于具体实现。对抽象进行编程,不要对实现编程。

依赖倒置原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。

其核心思想是:要面向接口编程,不要面向实现编程。

依赖倒置原则总结

  • 高层模块不应该依赖低层模块,应该依赖抽象
  • 接口或抽象不应该依赖于实现
  • 实现类应该依赖于接口或抽象类

接口隔离原则

客户端不应该依赖它不需要对接口,类间的依赖关系应该建立在最小接口上。简单来说就是接口尽量细化,方法尽量少。

我们所讲的接口主要分为两大类,一是实例接口,比如使用 new 关键字产生一种实例,被 new 的类就是实例类的接口。从这个角度出发的话,java 中的类其实也是一种接口。二是类接口,java 中常常使用 interface 关键字定义。

接口隔离原则总结

  • 接口尽量粒度化,保持接口纯洁性
  • 接口要高内聚,即减少对外交互

迪米特法则

也叫最少知识原则。定时是一个软件实体应该尽可能少的于其他实体发挥相互作用。迪米特法则的初衷在于降低类之间的聚合。

迪米特法则总结

  • 类定义时尽量内敛,少用public,尽量用private、protected

合成复用原则

将已有的对象纳入新对象中,作为新对象的成员对象来实现。新对象可以调用已有对象的功能,从而达到复用。尽可能使用聚合的方式,而不是使用继承。

都知道,类之间有三种基本关系,分别是:关联(聚合和组合)、泛化(与继承同一概念)、依赖。

这里我们提一下关联关系,客观来讲,大千世界中的两个实体之间总是有着千丝万缕的关系,归纳到软件系统中就是两个类之间必然存在关联关系。如果一个类单向依赖另一个类,那么它们之间就是单向关联。如果彼此依赖,则为相互依赖,即双向关联。

关联关系包括两种特例:聚合和组合。聚合,用来表示整体与部分的关系或者 “拥有” 关系。其中,代表部分的对象可能会被代表多个整体的对象所拥有,但是并不一定会随着整体对象的销毁而销毁,部分的生命周期可能会超越整体。好比班级和学生,班级销毁或解散后学生还是存在的,学生可以继续存在某个培训机构或步入社会,生命周期不同于班级甚至大于班级。

合成,用来表示一种强得多的 “拥有” 关系。其中,部分和整体的生命周期是一致的,一个合成的新的对象完全拥有对其组成部分的支配权,包括创建和泯灭。好比人的各个器官组成人一样,一旦某个器官衰竭,人也不复存在,这是一种 “强” 关联。

合成复用原则总结

  • 新对象可以调用已有对象功能,从而达到复用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值