1.什么是设计模式?
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。这些模式不仅可以加快开发速度,还可以提高代码的可读性、可维护性和可复用性。
2.你知道哪些设计模式
3.设计模式的原则有哪些
(1)单一职责原则(Single Responsibility Principle,SRP):一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
(2)开闭原则(Open-Closed Principle,OCP):一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
比如我们的程序员分为Java程序员、C#程序员、PHP程序员、前端程序员等,而他们要做的都是去打代码,具体如何打代码是根据不同语言的程序员来决定的,可以将程序员打代码这一个行为抽象成一个统一的接口或是抽象类,这样就满足了开闭原则的第一个要求:对扩展开放,不同的程序员可以自由地决定他们该如何进行编程。而具体哪个程序员使用什么语言怎么编程,是自己在负责,不需要其他程序员干涉,所以满足第二个要求:对修改关闭。
(3)里氏代换原则(Liskov Substitution Principle,LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。(即子类可以扩展父类的功能,但不能改变父类原有的功能)
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类可以增加自己特有的方法。
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松。
- 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或与父类一样。
(4)依赖倒转原则(Dependency Inversion Principle,DIP): 高层模块不应该依赖于低层模块,两者都应该依赖于抽象(接口或抽象类);抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
高层模块不依赖于低层模块:传统的设计中,高层模块直接依赖于低层模块,这会导致高层模块的代码与低层模块紧耦合,不利于系统的扩展和维护。依赖倒转原则要求高层模块和低层模块都依赖于抽象,从而实现解耦。
抽象不依赖于具体实现:抽象层(如接口或抽象类)不应该依赖于具体的实现类,而是应该通过依赖注入等方式,将具体的实现注入到抽象层中。
实现依赖倒转原则的方法:
使用接口或抽象类:定义接口或抽象类,通过依赖接口或抽象类来解耦具体实现。
依赖注入:通过构造函数注入、Setter方法注入或接口注入的方式,将具体的实现类注入到依赖抽象的类中。
(5)接口隔离原则(Interface Segregation Principle,ISP):使用多个专门的接口,而不使用单一的总接口,接口应该小而专一,避免臃肿;即客户端不应该依赖那些它不需要的接口。
(6)合成复用原则:优先使用对象组合来实现代码复用,而不是通过继承来实现。这一原则的核心思想是通过将功能分解成更小、更独立的组件,然后将这些组件组合在一起,以实现更复杂的功能。
优点:
- 灵活性高:对象组合可以在运行时动态地改变对象的行为,而继承只能在编译时决定。
- 降低耦合度:对象组合使得各个组件之间的耦合度降低,从而提高了系统的可维护性和可扩展性。
- 增强代码复用:通过组合可以更方便地复用代码,因为一个对象可以包含多个组件,每个组件都可以在不同的上下文中被复用。
实现方法:
- 接口和实现分离:将功能定义为接口,然后实现这些接口的具体类通过组合这些接口的实现类来实现复杂功能。
- 策略模式:使用策略模式,通过将算法封装在独立的策略类中,然后在运行时选择和组合不同的策略。
- 装饰者模式:通过装饰者模式,在不改变对象的基础上,动态地添加功能。
(7)迪米特法则(Law of Demeter,LoD):迪米特法则的核心思想是一个对象应尽可能少地了解其他对象,只与直接的朋友通信,而避免与陌生的对象通信。用于降低系统的耦合度,提高代码的可维护性和可扩展性。
4.设计模式的分类
设计模式通常分为三大类:
- 创建型模式:在创建对象的同时隐藏创建逻辑,不使用 new 直接实例化对象,程序在判断需要创建哪些对象时更灵活。包括工厂/抽象工厂/单例/建造者/原型模式。
- 结构型模式:通过类和接口间的继承和引用实现创建复杂结构的对象。包括适配器/桥接模式/过滤器/组合/装饰器/外观/享元/代理模式。
- 行为型模式: 通过类之间不同通信方式实现不同行为。包括责任链/命名/解释器/迭代器/中介者/备忘录/观察者/状态/策略/模板/访问者模式。