[译] 面向对象设计的十大戒律

 

《[译] 面向对象设计的十大戒律》

不不不,这句话可不是上帝说的.

也不是马丁路德金、南丁格尔、布鲁斯威尔士、周星驰说的.

我们做过代码审查,也讨论过为什么我们不遵循尝试原则的去做一些偷工减料的工作. 尽管每个人对于如何创建类都有一套自己的智慧,但做这些基础的类设计的工作时还是得有一些基础原则需要铭记于心.

I. 遵循单一职责原则

每一个类应该专注于做一件事情. 不仅仅是类,方法也应该是这样. 你有没有见过那些又长又臭的跟老太太的裹脚布一样的类啊方法什么的,如果把他们展开写在纸上的话,估计得有万里长城一半那么长了.  好吧,反正你别那么搞就行了.

这种原则允许类或者方法只有一种存在的理由(单一职责,只做一件事;哲学方面的东西么). 如果一个类的名字叫 Loan (贷款) 那么它应该去处理银行账户相关的内容. 同样如果一个方法的名字叫 GetLoanDetails (获取贷款细节)那么它只需要做好获取贷款细节的细节就好!

II. 遵循开闭原则

这种原则可以让你考虑系统如何适应未来的变化. 它规定,一个系统应当允许在已有代码的基础上以最小改动的方式来添加新功能. 因此, 这种原则实际上是面向扩展开放面向修改关闭的. 在我们的示例中, 开发者已经写了下面的一些代码:

public class PersonalLoan
{
    public void Terminate()
    {
        //Execute Termination related rules here and terminate a personal loan
    }
}

public class AutoLoan
{
    public void Terminate()
    {
        //Execute Termination related rules here and terminate a personal loan
    }
}

public class LoanProcessor
{
    public void ProcessEarlyTermination(object loan)
    {
        if ( loan is PersonalLoan )
        {
            //Personal Loan processing
        }
        else if (loan is AutoLoan)
        {
            //Auto Loan Processing
        }
    }
}

问题是LoadProcessor这个方法,一旦有新的贷款类型加入,就必须修改它,增加新的判断类型,例如加入了一个HomeLoan(家庭贷款类型)。所以一种更好的替代方案是这样的:

public abstract class Loan
{
    public abstract void Terminate();
}

public class PersonalLoan: Loan
{
    public override void Terminate()
    {
        //Execute Termination related rules here and terminate a personal loan
    }
}

public class AutoLoan: Loan
{
    public override void Terminate()
    {
        //Execute Termination related rules here and terminate a personal loan
    }
}

public class LoanProcessor
{
    public void ProcessEarlyTermination(Loan loan)
    {
        loan.Terminate();
    }
}

这样的话,添加新的贷款类型 LoadProcessor方法将不会受到影响.

 

III. 尝试使用组合而不是继承

如果没有适当的遵循这一原则,会导致类结构脆弱。这个原则很简单,而你只需要问一个问题——如果我打算访问子类,我是否能够说:子类是父类的一种类型?或者更确切的说,子类的一部分是父类的类型么?

对于这种情况我们通常使用继承,因为这保证了在所有父类能够使用的地方可以使用子类。这也能够允许你使用另一种叫做 Liskov替换原则 的原则。而在你想要部分使用类中的函数时,使用组合方法。

IV.封装数据和行为

大多数开发者只做数据封装,忘记封装基于上下文变化的代码。要知道不仅隐藏类中私有数据很重要,对作用与私有数据上的行为进行良好的封装同样很重要。

V. 遵循类的低耦合原则

这与封装正确的行为是相辅相成的。如果类中的行为被很好的封装,那么我们只能创建松散耦合的类。我们也可以通过抽象而不是实现来做到松散耦合。

VI. 类间高度内聚

数据和行为不应该在类间重复应用。我们需要尽量保证类的实现细节不会泄漏,这意味着不允许有代码超出目的而存在。当然,有一些设计范例如CQRS,能够帮助你将不同类型的行为分配到不同的类中,但是他们只用于分布式系统。

VII. 编码接口而不是实现

这能够促进低耦合,而且允许我们改变底层实现或引入新的实现而不影响使用它们的类。

VIII. 保持 DRY (Don’t Repeat Yourself)

不要在不同的地方重复使用相同的代码是 另一种设计原则 。因此,特定功能的函数或算法需要在一个地方实现且仅在这一个地方。如果重复实现方法会导致维护问题。与此相反的是WET原则——Write Everyting Twice。

IX. 最少知识原则:迪米特法则

这个原则声明对象不应该知道与他协作对象的内部细节。也以下面这句话闻名——只和朋友交流,而不是朋友的朋友。一个类只能调用它的协作类的公有数据成员,不应该被允许访问哪些数据成员组成的类的行为或数据。如果不能正确的遵守,会导致高耦合,难以对创建的系统进行修改。

X.遵守好莱坞原则: Don’t Call Us, We’ll Call You

这个原则打破了条件流逻辑模型,允许能够基于事件进行代码执行。这可以通过事件回调或者给出接口的实现来完成。依赖注入,控制翻转,或者观察者设计模型是这一原则的非常好的示例。这一原则也保证了类间的低耦合以及类的实现可维护。

    原文作者:算法小白
    原文地址: https://juejin.im/entry/582d54070ce463006ce7cd7e
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞