设计原则笔记

单一职责原则:

   对于一个类而言,应该只有一个发生变化的原因。(单一职责不仅仅是指类)

开闭原则(OCP):

  对拓展开发,对修改封闭。

  一个模块写好了,但是如果还想要修改功能,不要对模块本身进行修改,可能会引起很大的连锁反应,破坏现有的程序,应该通过扩展来进行实现。通过扩展来实现的前提,就是一开始把模块抽象出来,而抽象出来的东西要能够预测到足够多的可能,因为一旦确定后,该抽象就不能在发生改变。

  抽象化为关键

依赖倒置原则(DIP)

  依赖倒置原则主程序要依赖于抽象接口,不要依赖于具体实现。高层模块不应该依赖底层模块,两个都应该以来抽象。抽象不应该依赖细节,细节应该依赖抽象。

里氏替换原则(LSP)

  一个程序中如果使用的是一个父类,那么该程序一定适用于其子类,而且程序察觉不出父类和子类对象的区别。也就是说在程序中,把父类都替换成它的子类,程序的行为没有任何变化。

  总结下来实现里氏替换原则的根本就是,不要强行继承,如果继承就要完全实现。

接口隔离原则(ISP)

  客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上

  满足接口隔离原则的前提就是,接口不要设计的太过庞大,什么叫庞大呢?比如一个动物接口就非常庞大,因为如果细分的话,就可以分很多种类的动物,此时动物接口就需要考虑率足够多的情况来保证动物接口后续不被修改,那么一开始设计时,就可以将动物接口根据具体的需求(例如动物是否会飞和游泳)细分为水里游的动物、天上飞的动物和地上跑的动物,如果还是过于庞大,就再细分。

  就比如开闭原则中的IEat接口,就满足了接口隔离原则,该接口只负责吃的接口,所有需要吃的动物都可以实现该接口,而Feed喂食类依赖IEat接口,此时IEat接口也是最小接口。

public class Feed
{
    //使用接口接收,后续可以传入实现该接口的子类,因为用到了协变,就需要使用IEnumerable来接受
    public void StartFeed(IEnumerable<IEat> d, IFood f)
    {
        foreach (IEat item in d)
        {
            item.eat(f);
        }
    }
}

  让Feed喂食类依赖IAnimal:

public class Feed
{
    //使用接口接收,后续可以传入实现该接口的子类
    public void StartFeed(IEnumerable<IAnimal> d, IFood f)
    {
        foreach (IAnimal item in d)
        {
            item.eat(f);
        }
    }
}

这样的话就违反了接口隔离原则,因为Feed喂食类只需要调用对象的eat方法,动物的其他的方法都是不调用的,但是却依赖了IAnimal接口,这样的话就显得很臃肿,而且如果以后不传入动物,该工厂也负责喂养机器人吃电池,是不是依赖IAnimal就不合适了(如果非要让机器人实现IAnimal接口是可行的,不过这太不合理了)

迪米特法则(LoD)(最少知识原则(LKP))

  一个对象应当对其他对象有尽可能少的了解,不要和陌生人说话

  即尽可能少的写public方法和变量,不需要让别的对象知道的方法或者字段就不要公开。

上一篇:spring-事务服务中的ConstraintViolationException不回滚


下一篇:【luoguP4544】[USACO10NOV]购买饲料Buying Feed