2

软件设计七大原则

 2 years ago
source link: https://segmentfault.com/a/1190000040896720
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

软件设计七大原则

发布于 今天 15:55

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


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

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

普通计算器支持加减乘除

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

合成复用原则

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

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

类图:同单一职责原则


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK