嗨喽~小伙伴们,
今天,给大家简单地介绍一下设计模式。
关于设计模式,网上的资料有许多,结合笔者自己的理解,简单地谈一谈。
一:什么是设计模式?
查阅了许多资料,他们给出的定义基本一致:
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
合理地使用设计模式能够使代码编制真正工程化。经过好几辈科学家的探索和实践,他们总结出了许多合理且高效的模式和思想,比如“优先使用对象的组合而不使用继承”,再比如“针对接口编程,依赖于抽象而不依赖于具体”等等。
设计模式是软件工程的基石。在现实生活中所见到的许多原理,在设计模式中均有体现,设计模式是对客观存在事物的一种认知的结果,从现实生活中获得设计的灵感,然后应用于现实。
二:设计模式的基本原则有哪些?
网上对于设计模式的介绍,都会提到设计模式的“六大原则”,笔者在此谈谈自己对“六大原则”的理解。
1、开闭原则(Open Close Principle)
开闭原则的含义:对扩展开放,对修改关闭。现在的许多大型的应用开发,都会要求自己的程序扩展性好,所谓扩展性好,就是指在不修改原有代码的基础上,能够扩展新的功能。简单来说就一个目的:便于维护和升级。从当前主流开发模式中可以看到,要实现开闭原则,使用的都是接口和抽象类。通过编写接口和抽象类来维护已有的程序块,同时达到扩展业务功能的作用。
2、里氏代换原则(Liskov Substitution Principle)
里氏代换原则本是面向对象设计的基本原则之一。 简单来说就是,子类可以扩展父类的功能,但不能改变父类原有的功能。换句话说,在一个程序里,将某个基类换成它的任何一个子类,程序仍然能够正常地运行。由于使用基类对象的地方均可以使用子类对象,因此在程序中应尽量使用基类类型来对对象进行定义。里氏代换原则是实现开闭原则的重要方式之一,也是对实现抽象化的具体步骤的规范。
3、依赖倒转原则(Dependence Inversion Principle)
作为开闭原则的基础,就如笔者前面提到的:针对接口编程,依赖于抽象而不依赖于具体。也就是说,上层模块不应该依赖底层模块,而它们都应该依赖于抽象。咱可以举个例子加以理解。比如我们想要实现一家球店,实现一家球店,有许多的依赖:篮球,足球,羽毛球等,也就是说,如果缺少篮球,足球,羽毛球等(底层模块),球店(上层模块)便无法营业,这便是一个典型的“上层模块依赖底层模块”事例,而现在我们换个角度,从底层模块考虑,篮球,足球,羽毛球等能够抽象成什么?对了,它们均能够抽象成-----球。这样设计的话,你会发现,球店(上层模块),篮球,足球,羽毛球(底层模块),它们均依赖于----球(抽象)。这就很好诠释了“上层模块不应该依赖底层模块,而它们都应该依赖于抽象”。这样有什么好处呢?如果球店想要扩展业务范围,比如原来不卖某球的,现在想卖刚引进的某球,这时,你只需要实现球-----这个抽象就行了,比如,你可以将球实现为排球,实现为乒乓球......在实现的过程中,你会发现,你没有修改原有的底层模块,仅仅是扩展了球这一个抽象类,这不正好符合“开闭原则”吗?
4、接口隔离原则(Interface Segregation Principle)
这个原则很好理解,大致意思是:使用多个独立接口,比使用单个接口要好。如果只使用单个接口,由该接口实现的类与类之间,会有或多或少的依赖关系,比如子类与父类的关系,当一个项目比较大的时候,整个程序的所有类耦合在一起,一旦需要修改某个类,那么与这个类具有依赖关系的所有类,均会受到影响,在开发中应尽量避免这种情况。因此它还有一个意思:降低类之间的耦合度。
5、迪米特法则,又称最少知道原则(Demeter Principle)
最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。前面的“接口隔离原则”说到,同一接口,类与类之间会有一定的依赖关系,而“迪米特法则”则要求,尽量减少甚至消除这种依赖关系。
6、合成复用原则(Composite Reuse Principle)
合成复用原则很简单:尽量使用合成的方式,而不是使用继承。
通常类的复用分为继承复用和合成复用两种,继承复用虽然有简单和易实现的优点,但它也存在以下缺点:
- 继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类来说是透明的,这不符合“封装性”要求。
- 子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这显然不利于类的扩展与维护。
- 限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,在运行时不可能发生变化,灵活性不高。
采用组合或聚合复用时,可以将已创建的对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已创建对象的功能,因此它有如下优点:
- 维持了类的封装性。因为成员对象的内部细节对新对象而言是看不见的,从而保证了类的封装性。
- 新旧类之间的耦合度降低。这种复用所需的依赖较少,新对象存取成员对象的唯一方法是通过成员对象的接口。
- 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成员对象类型相同的对象。
以上就是笔者对“六大原则”的认识了,如果小伙伴们有更好,更独到的见解,欢迎评论区留言讨论,喜欢的小伙伴们点个赞鼓励支持一下吧~