关于stackoverflow的"开放封闭原则"主题已经有很多讨论.然而,似乎通常对该原理的更宽松的解释是普遍的,因此例如Eclipse可以通过插件进行修改.
根据严格的OCP,您应该修改原始代码只是为了修复错误,而不是添加新的行为.
在公共或OS库中是否有任何严格解释OCP的好例子,你可以通过OCP观察一个特征的演变:有一个类Foo,方法是bar(),而且还有一个FooDoingAlsoX和foo2()方法.库的下一个版本,其中原始类已被扩展,其中原始代码未被修改.
编辑:根据Robert C. Martin的说法:"模块的二进制可执行版本,无论是可链接库,DLL还是Java .jar都保持不变"*.我从未看到库保持关闭,实际上新的行为被添加到库中并且新版本已发布.根据OCP,新行为属于新的二进制模块.
*Robert C. Martin的敏捷软件开发,原则,模式和实践
DIP声明:
- 高级模块不应该依赖于低级模块.两者都应该取决于抽象.
- 抽象不应该依赖于细节.细节应取决于抽象.
OCP声明:
软件实体(类,模块,函数等)应该是可以扩展的,但是关闭以进行修改.
我认为如果我们满足DIP,它也会涵盖OCP,那么,为什么我们将这两个原则分开呢?
oop design-patterns open-closed-principle solid-principles dependency-inversion
我有以下结构可以使用开闭原理
class Payment{
//this is not a model class
// according to OC principle this class should not focus on the implementation
private $paymentInterface;
public function __construct(PaymentInterface $paymentInterface)
{
$this->paymentInterface = $paymentInterface;
}
//so store method does not know which implementation it will get
public function store($request,$id)
{
return $this->paymentInterface->store($request,$id);
}
}
Run Code Online (Sandbox Code Playgroud)
接口
interface PaymentInterface{
public function store($request,$id = null);
}
Run Code Online (Sandbox Code Playgroud)
包含实现的支付服务类
class PaymentService implements PaymentInterface{
public function store($request,$id = null){
//payment store logic is here
}
}
Run Code Online (Sandbox Code Playgroud)
控制者 …
简而言之,在 Java 的 LTS 版本 (Java 17) 中,我们第一次有了关键字sealed,它使我们能够限制层次结构:
public abstract sealed class Person
permits Employee, Manager {
//...
}
Run Code Online (Sandbox Code Playgroud)
如果我想创建一个扩展基类的新子类Person,我也必须修改基类。这是否违反开闭原则?
场景:我在类字段中存储了一些信息(例如,双精度数组)(比如字段Measurements,类中的整数数组MeasureData).现在我想使用这些数据来执行一些计算(例如,计算数组的算术平均值,最大值和最小值).此刻,我不知道在未来,我需要做的这些数据的任何其它操作(例如,也许我会需要得到标准差,总和或其他).我会有很多类型的对象MeasureData.
解决方案:我可以编写一个类Calculator,声明它是final,使用私有构造函数并使用几个静态方法来执行我需要的计算.这似乎是有道理的,因为它Calculator充当实用类,没有任何字段,就像标准Math类一样.
问题:如果在几个月内我需要进行任何其他计算,我将需要编写另一个静态方法Calculator.这是否意味着违反开放/封闭原则(毕竟,我正在修改类的实现Calculator)?
假设在我假设的软件的第一个版本中,我有一个像这样的简单类:
public Class Version1
{
public void Method1()
{
Console.WriteLine("Hello");
}
}
Run Code Online (Sandbox Code Playgroud)
在第二个版本中,我进行了升级,需要对方法 1 进行如下修改:
public Class Version1
{
public void Method1()
{
Console.WriteLine("Hello");
Console.WriteLine("World");
}
}
Run Code Online (Sandbox Code Playgroud)
在第三个版本中,我进行了升级,需要向此类添加另一个方法,如下所示:
public Class Version1
{
public void Method1()
{
Console.WriteLine("Hello");
Console.WriteLine("World");
}
public int Method2()
{
return 7;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,根据我对开闭原则的理解,在两次升级中,我都违反了这一原则,因为我修改了在我的软件的第一个版本中执行所需工作的类。
我认为应该这样做,但不确定是否正确,是这样的:
public virtual Class Version1
{
public virtual void Method1()
{
Console.WriteLine("Hello");
}
}
public virtual Class Version2 : Version1
{
public override void Method1()
{
Console.WriteLine("Hello");
Console.WriteLine("World");
}
}
public Class …Run Code Online (Sandbox Code Playgroud) Java 8 引入了接口默认实现的概念?这是否违反了开放封闭原则,因为基于https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html上的示例,您似乎始终可以打开界面以添加新功能?
architecture open-closed-principle default-implementation java-8 default-method
该单一职责原则指出:
一个班级应该有一个,而且只有一个,改变的理由。
在打开/关闭原则指出:
您应该能够扩展类行为,而无需修改它。
如果一个类应该只有一个改变的理由,但不应该被修改,那么开发人员怎么能同时尊重这两个原则呢?
例子
工厂模式是一个很好的例子,它具有单一职责,但可能违反开放/封闭原则:
public abstract class Product
{
}
public class FooProduct : Product
{
}
public class BarProduct : Product
{
}
public class ProductFactory
{
public Product GetProduct(string type)
{
switch(type)
{
case "foo":
return new FooProduct();
case "bar":
return new BarProduct();
default:
throw new ArgumentException(...);
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我需要ZenProduct在后期添加到工厂时会发生什么?
oop single-responsibility-principle open-closed-principle solid-principles
我有两个已检查的异常:TestException1和TestException2以及以下代码:
void p1() throws TestException1{
p2();
}
void p2() throws TestException1 {
p3();
}
void p3() throws TestException1 {}
Run Code Online (Sandbox Code Playgroud)
对p3的签名进行如下编辑是否违反了开闭原则?
void p3() throws TestException1, TestException2 {}
Run Code Online (Sandbox Code Playgroud) 本教程中的工厂显然违反了 OCP。每次在系统中添加一个形状,我们都需要在工厂中添加它以支持它。我正在考虑另一个实现,我想知道是否有任何缺点。
public class ShapeFactory {
//use getShape method to get object of type shape
public Shape getShape(Class<? extends Shape> shapeType){
return shapeType.newInstance();
}
}
Run Code Online (Sandbox Code Playgroud)
这个实现看起来不违反OCP,也不复杂。有什么原因我找不到任何提到它的工厂设计模式教程吗?
oop ×5
java ×3
architecture ×1
c# ×1
factory ×1
inheritance ×1
java-17 ×1
java-8 ×1
laravel ×1
php ×1
polymorphism ×1
sealed-class ×1