【java-软件设计原则】

java-软件设计原则

一、开闭原则

对扩展开放,对修改关闭。在程序需要扩展时,不能去修改原有的代码,实现热插拔的效果。为了使程序更好的进行维护和升级。

想要达到这样的效果,我们需要使用接口或者抽象类。

因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。

定义一个抽象类(AbstractSkin),而每个具体的皮肤(DefaultSpecificSkin和HeimaSpecificSkin)是其子类。用户窗体可以根据需要选择或者增加新的主题,而不需要修改原代码,所以它是满足开闭原则的。

举例:

定义一个抽象类AbstractSkin :

java 复制代码
public abstract class AbstractSkin {

    //显示的方法
    public abstract void display();
}

DefaultSkin 子类继承AbstractSkin 抽象类:

java 复制代码
public class DefaultSkin extends AbstractSkin{


    public void display() {
        System.out.println("默认皮肤");
    }
}

定义一个HeimaSkin类,继承AbstractSkin抽象类

java 复制代码
public class HeimaSkin extends AbstractSkin{


    public void display() {
        System.out.println("黑马皮肤");
    }
}

定义输入法类:可以根据setSkin()方法中传入的不同皮肤类型,实现不同的效果。

java 复制代码
public class SougouInput {

    private AbstractSkin skin;

    public void setSkin(AbstractSkin skin) {
        this.skin = skin;
    }

    public void display() {
        skin.display();
    }
}

测试类:创建SougouInput对象,可以创建不同的皮肤对象,调用setSkin()方法,将皮肤对象set到input对象中,实现不同皮肤显示。

java 复制代码
public class Client {

    public static void main(String[] args){
        //1.创建搜狗输入法对象

        SougouInput input = new SougouInput();
        //2.创建皮肤对象
        //DefaultSkin skin = new DefaultSkin();
        HeimaSkin skin = new HeimaSkin();
        //3.将皮肤设置到输入法中

        input.setSkin(skin);

        //4.显示皮肤
        input.display();
    }
}

二、里氏代换原则

子类可以实现扩展父类的功能,但不能改变父类原本的功能。

比如:

在数学领域里,正方形毫无疑问是长方形,它是一个长宽相等的长方形。所以,我们开发的一个与几何图形相关的软件系统,就可以顺理成章的让正方形继承自长方形。

代码如下:

java 复制代码
/**
 * 长方形类
 */
public class Rectangle {

    private  double length;

    private double width;

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }
}

/**
 * 正方形类
 */
public class Square extends Rectangle{

    @Override
    public void setLength(double length) {
        super.setLength(length);
        super.setWidth(length);
    }

    @Override
    public void setWidth(double width) {
        super.setWidth(width);
        super.setLength(width);
    }
}

正方形类继承了长方形类,重写了setWidth()方法和setLength()方法。

这违反了里氏代换原则。正确写法:

java 复制代码
/**
 * 四边形接口
 */
public interface Quadrilateral {

    //获取长
    double getLength();

    //获取宽
    double  getWidth();
}
* 长方形类
 */
public class Rectangle implements  Quadrilateral{

    private double length;

    private double width;

    public void setLength(double length) {
        this.length = length;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getLength() {
        return length;
    }

    public double getWidth() {
        return width;
    }
}
/**
 * 正方形
 */
public class Square implements Quadrilateral{

    private double side;

    public double getSide() {
        return side;
    }

    public void setSide(double side) {
        this.side = side;
    }

    public double getLength() {
        return side;
    }

    public double getWidth() {
        return side;
    }
}

先定义一个四边形接口,定义getLength()和getWith()函数,让正方形类和长方形类实现这个接口。重写方法。

三、依赖倒转原则

在开发中比较常见:

高层模块不直接依赖底层模块,两者都应该依赖于其抽象,要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

【例】组装电脑

现要组装一台电脑,需要配件cpu,硬盘,内存条。只有这些配置都有了,计算机才能正常的运行。选择cpu有很多选择,如Intel,AMD等,硬盘可以选择希捷,西数等,内存条可以选择金士顿,海盗船等。这个要求用代码实现出来,符合依赖倒置原则

先定义cpu和硬盘,内存接口:

java 复制代码
// CPU接口
interface CPU {
    String getBrand();
    String getModel();
    double getClockSpeed();
    void process();
}

// 硬盘接口
interface HardDisk {
    String getBrand();
    String getModel();
    int getCapacity();
    void readData();
    void writeData();
}

// 内存接口
interface Memory {
    String getBrand();
    String getModel();
    int getSize();
    int getSpeed();
    void storeData();
}

实现类:

java 复制代码
// CPU实现类
class IntelCPU implements CPU {
    private String model;
    private double clockSpeed;
    
    public IntelCPU(String model, double clockSpeed) {
        this.model = model;
        this.clockSpeed = clockSpeed;
    }
    
    @Override
    public String getBrand() {
        return "Intel";
    }
    
    @Override
    public String getModel() {
        return model;
    }
    
    @Override
    public double getClockSpeed() {
        return clockSpeed;
    }
    
    @Override
    public void process() {
        System.out.println(getBrand() + " " + model + " CPU正在处理数据,主频:" + clockSpeed + "GHz");
    }
}

class AMDCPU implements CPU {
    private String model;
    private double clockSpeed;
    
    public AMDCPU(String model, double clockSpeed) {
        this.model = model;
        this.clockSpeed = clockSpeed;
    }
    
    @Override
    public String getBrand() {
        return "AMD";
    }
    
    @Override
    public String getModel() {
        return model;
    }
    
    @Override
    public double getClockSpeed() {
        return clockSpeed;
    }
    
    @Override
    public void process() {
        System.out.println(getBrand() + " " + model + " CPU正在处理数据,主频:" + clockSpeed + "GHz");
    }
}

// 硬盘实现类
class SeagateHardDisk implements HardDisk {
    private String model;
    private int capacity; // GB
    
    public SeagateHardDisk(String model, int capacity) {
        this.model = model;
        this.capacity = capacity;
    }
    
    @Override
    public String getBrand() {
        return "Seagate";
    }
    
    @Override
    public String getModel() {
        return model;
    }
    
    @Override
    public int getCapacity() {
        return capacity;
    }
    
    @Override
    public void readData() {
        System.out.println(getBrand() + " " + model + " 硬盘正在读取数据,容量:" + capacity + "GB");
    }
    
    @Override
    public void writeData() {
        System.out.println(getBrand() + " " + model + " 硬盘正在写入数据,容量:" + capacity + "GB");
    }
}

class WD_HardDisk implements HardDisk {
    private String model;
    private int capacity; // GB
    
    public WD_HardDisk(String model, int capacity) {
        this.model = model;
        this.capacity = capacity;
    }
    
    @Override
    public String getBrand() {
        return "Western Digital";
    }
    
    @Override
    public String getModel() {
        return model;
    }
    
    @Override
    public int getCapacity() {
        return capacity;
    }
    
    @Override
    public void readData() {
        System.out.println(getBrand() + " " + model + " 硬盘正在读取数据,容量:" + capacity + "GB");
    }
    
    @Override
    public void writeData() {
        System.out.println(getBrand() + " " + model + " 硬盘正在写入数据,容量:" + capacity + "GB");
    }
}

// 内存实现类
class KingstonMemory implements Memory {
    private String model;
    private int size; // GB
    private int speed; // MHz
    
    public KingstonMemory(String model, int size, int speed) {
        this.model = model;
        this.size = size;
        this.speed = speed;
    }
    
    @Override
    public String getBrand() {
        return "Kingston";
    }
    
    @Override
    public String getModel() {
        return model;
    }
    
    @Override
    public int getSize() {
        return size;
    }
    
    @Override
    public int getSpeed() {
        return speed;
    }
    
    @Override
    public void storeData() {
        System.out.println(getBrand() + " " + model + " 内存正在存储数据,容量:" + size + "GB,频率:" + speed + "MHz");
    }
}

class CorsairMemory implements Memory {
    private String model;
    private int size; // GB
    private int speed; // MHz
    
    public CorsairMemory(String model, int size, int speed) {
        this.model = model;
        this.size = size;
        this.speed = speed;
    }
    
    @Override
    public String getBrand() {
        return "Corsair";
    }
    
    @Override
    public String getModel() {
        return model;
    }
    
    @Override
    public int getSize() {
        return size;
    }
    
    @Override
    public int getSpeed() {
        return speed;
    }
    
    @Override
    public void storeData() {
        System.out.println(getBrand() + " " + model + " 内存正在存储数据,容量:" + size + "GB,频率:" + speed + "MHz");
    }
}

计算机类,依赖于cpu和磁盘和内存:

java 复制代码
class Computer {
    // 依赖抽象,不依赖具体实现
    private CPU cpu;
    private HardDisk hardDisk;
    private Memory memory;
    
    // 通过构造函数注入依赖
    public Computer(CPU cpu, HardDisk hardDisk, Memory memory) {
        this.cpu = cpu;
        this.hardDisk = hardDisk;
        this.memory = memory;
    }
    
    // 也可以通过setter方法注入依赖
    public void setCpu(CPU cpu) {
        this.cpu = cpu;
    }
    
    public void setHardDisk(HardDisk hardDisk) {
        this.hardDisk = hardDisk;
    }
    
    public void setMemory(Memory memory) {
        this.memory = memory;
    }
    
    public void start() {
        System.out.println("=== 计算机启动中 ===");
        System.out.println("检查硬件配置:");
        System.out.println("CPU: " + cpu.getBrand() + " " + cpu.getModel());
        System.out.println("硬盘: " + hardDisk.getBrand() + " " + hardDisk.getModel());
        System.out.println("内存: " + memory.getBrand() + " " + memory.getModel());
        System.out.println();
    }
    
    public void run() {
        System.out.println("=== 计算机运行中 ===");
        cpu.process();
        memory.storeData();
        hardDisk.readData();
        System.out.println();
    }
    
    public void shutdown() {
        System.out.println("=== 计算机关闭中 ===");
        hardDisk.writeData();
        System.out.println("数据已保存,正在关闭...");
    }
    
    public void showSpecifications() {
        System.out.println("=== 计算机配置详情 ===");
        System.out.println("CPU:");
        System.out.println("  品牌: " + cpu.getBrand());
        System.out.println("  型号: " + cpu.getModel());
        System.out.println("  主频: " + cpu.getClockSpeed() + " GHz");
        
        System.out.println("\n硬盘:");
        System.out.println("  品牌: " + hardDisk.getBrand());
        System.out.println("  型号: " + hardDisk.getModel());
        System.out.println("  容量: " + hardDisk.getCapacity() + " GB");
        
        System.out.println("\n内存:");
        System.out.println("  品牌: " + memory.getBrand());
        System.out.println("  型号: " + memory.getModel());
        System.out.println("  容量: " + memory.getSize() + " GB");
        System.out.println("  频率: " + memory.getSpeed() + " MHz");
        System.out.println();
    }
}

四、接口隔离原则(单一职责原则)

客户端不应该被迫依赖于它不使用的方法;一个类对另一个类的依赖应该建立在最小的接口上。

例:

java 复制代码
// ==================== 第一层:基本行为接口 ====================

/**
 * 基础工作接口 - 只包含最基本的工作行为
 */
interface Workable {
    void work();
}

/**
 * 可进食接口 - 只包含进食行为
 */
interface Eatable {
    void eat();
}

/**
 * 可睡眠接口 - 只包含睡眠行为
 */
interface Sleepable {
    void sleep();
}

// ==================== 第二层:专业能力接口 ====================

/**
 * 程序员接口 - 包含编程相关行为
 */
interface Programmer {
    void code();
    void debug();
}

/**
 * 设计师接口 - 包含设计相关行为
 */
interface Designer {
    void design();
    void prototype();
}

/**
 * 测试工程师接口 - 包含测试相关行为
 */
interface Tester {
    void test();
    void reportBug();
}

/**
 * 运维工程师接口 - 包含部署相关行为
 */
interface DevOps {
    void deploy();
    void monitor();
}

// ==================== 具体实现类 ====================

/**
 * 全栈工程师 - 实现多个相关接口
 */
class FullStackDeveloper implements Workable, Programmer, Designer, Tester, DevOps {
    @Override
    public void work() {
        System.out.println("全栈工程师正在工作");
    }
    
    @Override
    public void code() {
        System.out.println("全栈工程师正在编写代码");
    }
    
    @Override
    public void debug() {
        System.out.println("全栈工程师正在调试代码");
    }
    
    @Override
    public void design() {
        System.out.println("全栈工程师正在设计系统架构");
    }
    
    @Override
    public void prototype() {
        System.out.println("全栈工程师正在制作原型");
    }
    
    @Override
    public void test() {
        System.out.println("全栈工程师正在进行单元测试");
    }
    
    @Override
    public void reportBug() {
        System.out.println("全栈工程师正在报告缺陷");
    }
    
    @Override
    public void deploy() {
        System.out.println("全栈工程师正在部署应用");
    }
    
    @Override
    public void monitor() {
        System.out.println("全栈工程师正在监控系统");
    }
}

/**
 * 人类员工 - 按需实现接口
 */
class HumanEmployee implements Workable, Eatable, Sleepable {
    private String name;
    private String position;
    
    public HumanEmployee(String name, String position) {
        this.name = name;
        this.position = position;
    }
    
    @Override
    public void work() {
        System.out.println(name + "(" + position + ")正在工作");
    }
    
    @Override
    public void eat() {
        System.out.println(name + "正在员工餐厅吃饭");
    }
    
    @Override
    public void sleep() {
        System.out.println(name + "正在休息室小憩");
    }
}

/**
 * 机器人程序员 - 只实现必要的接口
 */
class RobotProgrammer implements Workable, Programmer {
    private String model;
    
    public RobotProgrammer(String model) {
        this.model = model;
    }
    
    @Override
    public void work() {
        System.out.println(model + "机器人正在工作");
    }
    
    @Override
    public void code() {
        System.out.println(model + "机器人正在高效编写代码");
    }
    
    @Override
    public void debug() {
        System.out.println(model + "机器人正在分析并修复bug");
    }
}

/**
 * 专职测试机器人 - 专注测试工作
 */
class TestingRobot implements Workable, Tester {
    @Override
    public void work() {
        System.out.println("测试机器人开始工作");
    }
    
    @Override
    public void test() {
        System.out.println("测试机器人正在执行自动化测试");
    }
    
    @Override
    public void reportBug() {
        System.out.println("测试机器人正在生成测试报告");
    }
}

/**
 * 管理类 - 只依赖最小接口
 */
class WorkManager {
    public void manageWork(Workable worker) {
        worker.work();
    }
}

class Restaurant {
    public void serveFood(Eatable eater) {
        eater.eat();
    }
}

class RestRoom {
    public void allowRest(Sleepable sleeper) {
        sleeper.sleep();
    }
}

代码中创建了Workable、Eatable、Sleepable等基本行为接口和Programmer、Designer等专业技能接口,不同类按需组合实现。机器人程序员只实现Workable和Programmer接口而无需实现Eatable,人类员工则根据角色组合不同接口。WorkManager、Restaurant等客户端类只依赖各自需要的最小接口,避免了强迫类实现不相关方法,提高了系统的灵活性和可维护性。

相关推荐
JH30732 小时前
为什么switch不支持long
java
gpfyyds6662 小时前
Python代码练习
开发语言·python
盐真卿2 小时前
python第八部分:高级特性(二)
java·开发语言
茉莉玫瑰花茶2 小时前
C++ 17 详细特性解析(5)
开发语言·c++·算法
上海合宙LuatOS2 小时前
LuatOS核心库API——【audio 】
java·网络·单片机·嵌入式硬件·物联网·音视频·硬件工程
lly2024062 小时前
《堆的 shift down》
开发语言
汤姆yu2 小时前
基于springboot的尿毒症健康管理系统
java·spring boot·后端
TT哇2 小时前
【实习】银行经理端线下领取扫码功能实现方案
java
野犬寒鸦2 小时前
从零起步学习JVM || 第一章:类加载器与双亲委派机制模型详解
java·jvm·数据库·后端·学习