软件设计七大原则

开闭原则
依赖倒置原则
单一职责原则
接口隔离原则
迪米特法则
里氏替换原则
合成复用原则


代码开发遵循设计原则,使代码结构有条理且易于扩展和维护。并不需要生硬地按照软件设计原则去实现,而是根据不同的场景,选取比较合适的设计原则。

开闭原则

含义:一个软件实体,如类、模块和函数要对扩展开放,对修改关闭。在一个基础类上要增加功能时,不要去修改类中的代码,而是新增类继承基础类,在新增类中增加功能。

示例:

普通计算器支持加减乘除

public class GeneralCalculator {
  public int add(int x, int y){
      return x + y;
  }
  public int sub(int x, int y){
      return x - y;
  }
  public int mul(int x, int y){
      return x * y;
  }
  public int div(int x, int y){
      return x / y;
  }
}

科学计算器支持幂运算和普通运算

public class ScientificCalculator extends GeneralCalculator {
  public int power(int x, int y){
      if (x == 0){
          return 0;
      }
      if (y == 0){
          return 1;
      }
      int sum = 1;
      for (int i = 0; i < y; i++) {
          sum = mul(sum, x);
      }
      return sum;
  }
}

类图:

image-20211101215036285

依赖倒置原则

含义:抽象不应该依赖于细节,细节应当依赖于抽象。就是针对接口编程,在任何使用对象的地方都是用抽象类型,比如返回类型、成员变量和方法参数等。

示例:

人吃水果,可以吃苹果香蕉等

public interface IFruits {
  String getName();
}

public class Apple implements IFruits {
  public String getName() {
      return "苹果";
  }
}

public class Banana implements IFruits {
  public String getName() {
      return "香蕉";
  }
}

public class Person {
  public void eat(IFruits fruits){
      System.out.println("我正在吃" + fruits.getName());
  }
}

public class TestMain {
  public static void main(String[] args) {
      Person person = new Person();
      IFruits apple = new Apple();
      person.eat(apple);
  }
}

类图:

image-20211101223819572

单一职责原则

含义:一个类、方法或接口只实现一个功能。比如方法的命名都是见名知意,一个方法内容不要包含多种处理逻辑。

示例:电商下单流程有创建订单、扣减库存、支付。这是三个模块各自单独用一个类表示一个服务,每个服务都有自己独立的功能,不把这三个功能放到同一个类中。

public class OrderService {
  public void createOrder(){
      System.out.println("创建订单");
  }
}

public class StockService {
  public void subStock(){
      System.out.println("扣减库存");
  }
}

public class PayService {
  public void pay(){
      System.out.println("支付成功");
  }
}

public class TestMain {
  public static void main(String[] args) {
      new OrderService().createOrder();
      new StockService().subStock();
      new PayService().pay();
  }
}

类图:

image-20211101221900606

接口隔离原则

含义:建立多个专门的接口,不要建立笼统的接口。多个方法不应该在一个接口中,应该建立多个接口,放置一种类型的方法。

示例:有飞机、汽车、轮船三种交通工具

接口不能定义成这样,不然每一个实现类都要实现这三个接口,导致代码的冗余

public interface IVehicle {
  /**
    * 飞
    */
  void fly();

  /**
    * 行驶
    */
  void run();

  /**
    * 航行
    */
  void sail();
}

正确示例如下

public interface IFlyVehicle {
  /**
    * 飞
    */
  void fly();
}

public interface IRunVehicle {
  /**
    * 行驶
    */
  void run();
}

public interface ISailVehicle {
  /**
    * 航行
    */
  void sail();
}

public class Plane implements IFlyVehicle {
  public void fly() {
      System.out.println("飞机飞行");
  }
}

public class Car implements IRunVehicle {
  public void run() {
      System.out.println("汽车行驶");
  }
}

public class Ship implements ISailVehicle {
  public void sail() {
      System.out.println("轮船行驶");
  }
}

类图:

image-20211101225252303

迪米特法则

含义:迪米特法则又叫最少知道原则。类与类之间的应用尽量保持直接应用,一个类中尽量少导入别的类。

示例:司机开车送老板去机场

错误示例:老板类中没必要引入汽车这个类,司机引入这个类即可

public class Car {
  public void run(){
      System.out.println("汽车行驶中");
  }
}

public class Driver {
  public void driveCar(Car car){
      car.run();
  }
}

public class Boss {
  public void goAirport(Driver driver){
      Car car = new Car();
      driver.driveCar(car);
  }
}

public class TestMain {
  public static void main(String[] args) {
      Boss boss = new Boss();
      Driver driver = new Driver();
      boss.goAirport(driver);
  }
}

类图:

image-20211101231647202

正确示例:

public class Car {
  public void run(){
      System.out.println("汽车行驶中");
  }
}

public class Driver {
  public void driveCar(){
      Car car = new Car();
      car.run();
  }
}

public class Boss {
  public void goAirport(Driver driver){
      driver.driveCar();
  }
}

public class TestMain {
  public static void main(String[] args) {
      Boss boss = new Boss();
      Driver driver = new Driver();
      boss.goAirport(driver);
  }
}

类图:

image-20211101231912300

里氏替换原则

含义:一个软件实体如果适用一个父类,那么也一定要能适用于其子类,引用父类的地方,能替换成适用其子类,保证程序逻辑不变。

子类可以实现父类的抽象方法,也可以增加自己的功能,但不要覆盖非抽象方法;

示例:这边要和依赖倒置原则区分,依赖倒置原则注重的是模块依赖抽象接口;里氏替换原则注重的是子类与父类的关系。

司机可以开车,奥托奔驰都可以,奔驰多一个车载冰箱功能

public interface ICar {
  void run();
}

public class Alto implements ICar {
  public void run() {
      System.out.println("行驶");
  }
}

public class BenzCar implements ICar {
  public void run() {
      System.out.println("行驶");
  }

  private void codeStorage(){
      System.out.println("具有冰箱冷藏功能");
  }
}

public class TestMain {
  public static void main(String[] args) {
      Alto alto = new Alto();
      BenzCar benzCar = new BenzCar();
      Driver driver = new Driver();
      driver.driveCar(alto);
      driver.driveCar(benzCar);
  }
}

类图:

image-20211101234019650

合成复用原则

含义:实现功能复用,采用对象组合的方式。一个新类要使用另一个类的已有功能,可以去引用类,而不是去继承类。

示例:同单一职责原则,一个服务要实现下单功能,则同时引入订单服务、库存服务、支付服务,而不是去继承服务

类图:同单一职责原则



posted @ 2021-11-01 23:54  李胖胖不胖  阅读(192)  评论(0编辑  收藏  举报