六大设计原则

1. 单一职责原则

当对实现多种功能的对象进行修改了,可能牵一发而动全身。因此最好对象只做一件事,便于代码维护和拓展。
此举能够降低类的复杂度,一个类负责一件事,便于代码维护。

优点

  • 代码的粒度降低了,类的复杂度降低了。
  • 可读性提高了,每个类的职责都很明确,可读性自然更好。
  • 可维护性提高了,可读性提高了,一旦出现 bug ,自然更容易找到他问题所在。
  • 改动代码所消耗的资源降低了,更改的风险也降低了。

2. 开闭原则

软件更新应该对扩展开放,对修改关闭。
在软件的生命周期内,因为变化,升级和维护等原因需要对软件原有代码进行修改,可能会给旧代码引入错误,也有可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。

优点

  • 尽量通过扩展软件实体的行为来实现变化

  • 不需要对功能重构,直接在上方建房子

  • 不会引发原有功能产生bug

**用抽象构建架构,用实现扩展细节 。**因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保证架构的稳定。当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了,当然前提是抽象要合理,要对需求的变更有前瞻性和预见性。


3. 里氏替换原则

所有父类存在的场景均能用子类代替
里氏替换指所有基类都存在的地方,都可以换成子类。此举与继承有关,那么先讲下继承的优缺点。

继承的优点:

  • 子类拥有父类的所有方法和属性,从而可以减少创建类的工作量。
  • 提高了代码的重用性。
  • 提高了代码的扩展性,子类不但拥有了父类的所有功能,还可以添加自己的功能。

继承的缺点:

  • 继承是侵入性的,只要继承,子类就必须拥有父类的属性和方法。

  • 降低了代码的灵活性,父类对子类有一种约束。

  • 增强了耦合性,修改父类代码时必须考虑到对子类的影响

    1. 子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象(已实现)方法。
public class human
{
    void walk()
    {
        cout << "人会走路" << end;      // 人的特征
    }
};
public class Asia : public human
{
    void walk()
    {
        // 修改了人的特征,那么子类就不是人了,因此不能重写 父类 已实现的方法
        cout << "人会飞" << end;        
    }
}
  1. 子类中可以增加自己特有的方法。

  2. 当子类重载或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松

public class human
{
    void eat(Food food)         // 传入的是食物
    {
        cout << "吃食物的是人" << end;      // 人的特征
    }
};
public class Asia : public human
{
    void eat(vegetables ve)    // 传入的是蔬菜,蔬菜是食物的子类
    {
        cout << "吃蔬菜的是亚洲人" << end;        
    }
}
public class cly
{
    public static void main(String[] args)
    {
        // 蔬菜是食物,因此传入蔬菜时我希望得到结果为人
        Asia asia = new Asia();
        vegetables v = new vegetables();
        
        asia.eat(v).        // 输出吃蔬菜的是亚洲人,错误
    }
}
  1. 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。若在继承时,子类的方法返回值类型范围比父类的方法返回值类型范围大,在子类重写该方法时编译器会报错。(java语法)

4. 迪米特原则

一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。如果两个实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。

优点

  • 降低了类之间的耦合度,提高了模块的相对独立性。

  • 由于亲合度降低,从而提高了类的可复用率和系统的扩展性。

缺点

  • 过度使用会造成系统产生大量的中介类,从而增加系统的复杂度

实现方法

  • 从依赖者的角度来说,只依赖应该依赖的对象。 // 我只需要必要的资源,其他资源与我无关

  • 从被依赖者的角度说,只暴露应该暴露的方法。 // 我提供你要的资源,其他资源与你无关


5. 接口隔离原则

5.1 介绍

  • 客户端不应该依赖它不需要的接口
  • 类间的依赖关系应该建立在最小的接口上
  • 要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

5.2 优缺点

  • 将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
  • 接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。
  • 如果接口的粒度大小定义合理,能够保证系统的稳定性;但是,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。
  • 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
  • 能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码。

5.3 实现方法

  • 根据接口隔离原则拆分接口时,首先必须满足单一职责原则。
  • 接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。
  • 为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
  • 了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同,应该深入了解业务逻辑。
  • 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。

6. 依赖倒置原则

6.1 定义
上层模块不应该依赖底层模块,它们都应该依赖于抽象
抽象不应该依赖于细节,细节应该依赖于抽象

6.2 描述
将具体细节抽象化,形成细节依赖抽象,且上层模块也依赖抽象

6.3 优点
降低模块之间的耦合,同时便于功能的扩展

7. 合成复用原则

在一个对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分。新对象通过委派调用已有对象的方法达到复用其已有功能的目的。尽量少用继承。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值