SOLID –开闭原理

开放式封闭原则(OCP)指出,
对于扩展,软件实体(类,模块,功能)应为OPEN,对于修改应为关闭。

让我们试着反省一下以上声明:一旦编写,就不应修改软件实体以添加新功能,而必须对其进行扩展以添加新功能。

换句话说,您不会触摸现有模块,因此不会干扰现有功能,而是您可以扩展模块以实现新要求。 因此,您的代码不那么僵化,脆弱,也可以扩展。

OCP术语由Bertnard Meyer创造。

我们如何确认OCP原则?

简单-允许模块(类)依赖抽象,可以通过创建这些抽象的新扩展来添加新功能。

让我尝试用一​​个例子来解释:

假设您正在编写一个用于批准个人贷款的模块,并且在执行此操作之前,您想验证个人信息,那么按照代码明智的方式,我们可以将情况描述为:

public class LoanApprovalHandler
{
  public void approveLoan(PersonalValidator validator)
  {
    if ( validator.isValid())
    {
      //Process the loan.
    }
  }
}
public class PersonalLoanValidator
{
  public boolean isValid()
  {
    //Validation logic
  }
}

到目前为止,一切都很好。 大家都知道,要求从来都不是相同的,现在批准汽车贷款,消费品贷款以及其他什么都不是。 因此,解决此要求的一种方法是:

public class LoanApprovalHandler
{
  public void approvePersonalLoan (PersonalLoanValidator validator)
  {
    if ( validator.isValid())
    {
      //Process the loan.
    }
  }
  public void approveVehicleLoan (VehicleLoanValidator validator )
  {
    if ( validator.isValid())
    {
      //Process the loan.
    }
  }
  // Method for approving other loans.
}
public class PersonalLoanValidator
{
  public boolean isValid()
  {
    //Validation logic
  }
}
public class VehicleLoanValidator
{
  public boolean isValid()
  {
    //Validation logic
  }
}

我们已经编辑了现有的类别以适应新的要求-在此过程中,我们最终更改了现有方法的名称,并为不同类型的贷款批准添加了新方法。 这显然违反了OCP。 让我们尝试以另一种方式实现需求:

/**
 * Abstract Validator class
 * Extended to add different
 * validators for different loan type
 */
public abstract class Validator
{
  public boolean isValid();
}
/**
 * Personal loan validator
 */
public class PersonalLoanValidator
  extends Validator
{
  public boolean isValid()
  {
    //Validation logic.
  }
}
/*
 * Similarly any new type of validation can
 * be accommodated by creating a new subclass
 * of Validator
 */

现在,使用上述验证器,我们可以编写一个LoanApprovalHandler来使用Validator抽象。

public class LoanApprovalHandler
{
  public void approveLoan(Validator validator)
  {
    if ( validator.isValid())
    {
      //Process the loan.
    }
  }
}

因此,为了适应任何类型的贷款验证器,我们只需要创建Validator的子类,然后将其传递给approveLoan方法即可。 这样,该类关闭以进行修改,而打开以进行扩展。

另一个例子:

我在考虑另一个可以使用OCP原理的假设情况。 情况是这样的:“我们维护一个学生名单,包括他们的标记,唯一的标识(uid)以及姓名。 然后,我们提供一个选项,以uid-percentage名称值对的形式获取百分比。”

class Student
{
  String name;
  double percentage;
  int uid;
  public Student(String name, double percentage, int uid)
  {
    this.name = name;
    this.percentage = percentage;
    this.uid = uid;
  }
}

我们将学生名单收集到一个通用班级中:

class StudentBatch {
  private List<Student> studentList;
  public StudentBatch() {
    studentList = new ArrayList<Student>();
  }
  public void getSutdentMarkMap(Hashtable<Integer, Double> studentMarkMap) {
    if (studentMarkMap == null) {
      //Error
    } else {
      for (Student student : studentList) {
        studentMarkMap.put(student.uid, student.percentage);
      }
    }
  }
  /**
   * @param studentList the studentList to set
   */
  public void setStudentList(List<Student> studentList) {
    this.studentList = studentList;
  }
}

假设我们需要按插入顺序维护Map中元素的顺序,因此我们必须编写一个新方法来按插入顺序获取地图,为此,我们将使用LinkedHashMap。 相反,如果方法getStudentMarkMap()依赖于Map接口而不是Hashtable具体实现,则可以避免更改StudentBatch类,而传入LinkedHashMap实例。

public void getSutdentMarkMap(Map<Integer, Double> studentMarkMap) {
    if (studentMarkMap == null) {
      //Error
    } else {
      for (Student student : studentList) {
        studentMarkMap.put(student.uid, student.percentage);
      }
    }
  }

PS:我知道Hashtable是一个过时的集合,不鼓励使用。 但是我认为这将为OCP原理提供另一个有用的例子。

使代码更接近确认OCP的一些方法:

将所有成员变量设为私有,以便代码的其他部分通过方法(获取程序)而非直接访问它们。
避免在运行时进行类型转换-这使代码易碎且依赖于所考虑的类,这意味着任何新类都可能需要编辑该方法以适应新类的类型转换。

Robert Martin在OCP上写的非常好的文章

参考:我们的JCG合作伙伴 Mohamed Sanaulla“ Experiences Unlimited”博客中提供的 SOLID-开放封闭原则

相关文章 :

翻译自: https://www.javacodegeeks.com/2011/11/solid-open-closed-principle.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值