Java 开闭原则查询

Java 开闭原则查询,java,solid-principles,open-closed-principle,Java,Solid Principles,Open Closed Principle,简单介绍一下,遵循开闭原则,如果你有这样一个类: public class Employee extends Person { int age; String name; Employee(int age, String name) { super(age, name) } // Getters and setters follow } 如果你想添加一个额外的字段,比如说一个地址,这不是打破了开放/封闭原则吗 我只是好奇,如果

简单介绍一下,遵循开闭原则,如果你有这样一个类:

public class Employee extends Person {
    int age;
    String name;

    Employee(int age, String name) {
        super(age, name)
    }
    
    // Getters and setters follow
}
如果你想添加一个额外的字段,比如说一个地址,这不是打破了开放/封闭原则吗

我只是好奇,如果你违反了这个原则,你会如何创建这个类来解决这个问题

谢谢

简短的回答是“是”。这将违反OCP。因此,为了回答您的问题(您将如何创建类来解决此问题),让我们先看看OCP是什么:

开闭原理 OCP规定软件实体(类、模块、函数等)应打开以进行扩展,但关闭以进行修改

你清楚地理解了最后一部分,但似乎没有理解第一部分。同样,对您的问题的简短回答是简单地扩展您原来的类

public class Person {
   int age;
   String name;
   // rest of class omitted
}


这就是在添加新功能时如何遵守OCP。显然,如果这被滥用,它会导致班级爆炸,这也是很糟糕的。作为一名开发人员(和设计师),您必须盲目尊重这一原则,反对创建深层层次链

需要记住的是,OCP(与SOLID的其余部分一样)只是建议。最后,如果您发现自己处于这种情况,它可能是仓促设计决策的一个指标(直接执行而没有花足够的时间来巩固您的设计)。因此,不要再草率地执行决定,停止并考虑重新设计最初创建的内容(即考虑继承而不是合成)。@hfontanez为OCP提供了一个很好的高层介绍,你可以在大多数与OCP相关的答案中看到这一点

但长话短说的答案是“不”。因为OCP在这里不适用。
为了理解我们需要担心OCP的场景类型,我们必须从适当的编程范式开始。OCP和所有坚实的原则一样,是面向对象的。它适用于面向对象的代码

Employee
在OO这个词的意义上不是对象,因为对象具有行为
Employee
是一种数据结构:它纯粹是状态的表示。数据结构是过程编程和函数编程的基础,但不是OO。试图将OCP应用于
员工
从一开始就将我们置于错误的轨道上,因为我们处于错误的范式中

解决范式问题似乎微不足道。我们可以在
Employee
中实现
doWork()
方法,然后我们就有了一些行为,对吗?但这正是坚实的原则开始相互作用的地方。因为谁将调用
doWork()
方法?当然不是
员工
模块之外的任何客户!毕竟,
Employee
是一个具体的实现,依赖倒置原则规定了对抽象的依赖,而不是具体的依赖

同样,我们可能会找到一个微不足道的解决方案。将
doWork()
方法提取到由
Employee
实现的接口。现在客户端可以在遵循DIP的同时调用它。(由于我们正在考虑坚实原则的相互作用,还假设
doWork()
的实现遵守其抽象声明的约定,这样我们就不会违反LSP。)

当然,现在OCP适用于员工,对吗?它既有状态又有行为(使其成为一个成熟的OO对象),并通过适当的抽象来公开其行为。但是OCP仍然不适用。。。因为
Employee
现在是一个实现细节。根据OCP,“关闭”的定义包括发布供客户(即公众)使用。实施细节不在此定义中

因此,通过结合坚实的原则,我们得出了一个重要结论

OCP严格适用于面向对象应用程序或库的公共、抽象、API


请随意编辑您的实现细节。OCP不介意。

是的。总是考虑重构之前添加层CRUD(不CRUD:-)…如果你不这样做,你最终将不得不重构或重写,而且以后会更加痛苦和昂贵。啊,好吧,有些东西足够大,可以进行更改,你应该有一个扩展当前类的新类。完美的描述,非常感谢:)我不想编辑我的答案,我只想评论一下,有了这个“解决方案”,现在你就有了Liskov替换原理的问题。这是我答案的核心:在实施解决方案之前,停止并重新评估。
// This class already obeyed OCP by extending Person and adding new attributes and behaviors (took the liberty to change your original class for a good reason - See Person class)
public class Employee extends Person {
   String empID;
   // Rest of the class omitted
}
// Simply add one more (corny class name, sorry)
public class AddressableEmployee extends Employee {
   private String address;
   // Rest of the class omitted
}