设计模式:是一套被反复使用,多数人知晓的,经过分类的,代码设计经验的总结。
使用设计模式是为了代码的可重用性,让代码更容易被他人理解,保证代码可靠性。
设计模式的分类:java中存在着23种设计模式,这么多设计模式,大体上可以分为三大类,分别是:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)和行为型模式(Behavioral Patterns);最后还有一种设计模式:J2EE设计模式。
模式 | 包括 |
创建型模式 这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方 式;而不是使用new运算符直接实例化对象。这使得程序在判 断针对某个给定实例需要创建哪些对象时更加灵活。 | 工厂模式(Factory Pattern) |
抽象工厂模式(Abstract Factory Pattern) | |
单例模式(Singleton Pattern) | |
建造者模式(Builder Pattern) | |
原型模式(Prototype Pattern) | |
结构型模式 这些设计模式关注类和对象的组合。继承的概念被用来组合接 口和定义组合对象获得新功能的方式。 | 适配器模式(Adapter Pattern) |
桥接模式(Bridge Pattern) | |
过滤器模式(Filter、Criteria Pattern) | |
组合模式(Composite Pattern) | |
装饰器模式(Decorator Pattern) | |
外观模式(Facade Pattern) | |
享元模式(Flyweight Pattern) | |
代理模式(Proxy Pattern) | |
行为型模式 这些设计模式特别关注对象之间的通信。 | 责任链模式(Chain of Responsibility Pattern) |
命令模式(Command Pattern) | |
解释器模式(Interpreter Pattern) | |
迭代器模式(Iterator Pattern) | |
中介者模式(Mediator Pattern) | |
备忘录模式(Memento Pattern) | |
观察者模式(Observer Pattern) | |
状态模式(State Pattern) | |
空对象模式(Null Object Pattern) | |
策略模式(Strategy Pattern) | |
模板模式(Template Pattern) | |
访问者模式(Visitor Pattern) | |
J2EE模式 这些设计模式特别关注表示层,是由Sun Java Center鉴定的。 | MVC模式(MVC Pattern) |
业务代表模式(Business Delegate Pattern) | |
组合实体模式(Composite Entity Pattern) | |
数据访问对象模式(Data Access Object Pattern) | |
前端控制器模式(Front Controller Pattern) | |
拦截过滤器模式(Intercepting Filter Pattern) | |
服务定位器模式(Service Locator Pattern) | |
传输对象模式(Transfer Object Pattern) |
面向对象设计模式中存在的五大原则和一个法则:
五大原则:
- 单一职责SRP(Single Responsibilities Principle)
- 开闭原则OCP(Open Close Principle)
- 里氏代换LSK(Liskov Substitution Principle)
- 倒转依赖DIP(Dependence Inversion Principle)
- 接口隔离ISP(Interface Segregation Principle)
一个法则:
- 迪米特DP(Demeter Principle)
一、单一职责原则
定义:不要存在多于一个导致类变更的原因。也就是说,一个类只负责一项职责,应该仅有一个引起它变化的原因。
优点:
- 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多。
- 提高类的可读性,提高系统的可维护性。
- 变更引起的风险降低,变更时必然的,如果单一职责原则遵守的好,只要是模块化的程序设计,都需要遵循这一重要原则。
二、开放封闭原则
定义:一个软件实体如类,模块和函数应该对扩展开放,对修改关闭。
需求总是变化的,OCP给了我们如下的建议:在发生变化的时候,不要修改类的源代码,要通过增加新代码来增强现有类的行为。如何才能在不改动源代码的情况下去更改它的行为呢?答案就是抽象(Interface和抽象基类)。实现OCP的核心思想就是对抽象编程,让类依赖于固定的抽象,对修改就是封闭的,而通过面向对象的继承和多态机制,通过覆写方法改变固有行为,实现新的扩展方法,对于扩展就是开放的。
三、里氏代换原则
定义:子类型必须能够替换掉它们的父类型。
里氏代换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类中可以增加自己特有的方法。
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
四、倒转依赖原则
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。即针对接口编程,不要针对实现编程。
倒转依赖原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节指的就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给它们的实现类去完成。
倒转依赖原则的中心思想是面向接口编程,传递依赖关系有三种方式:接口传递,构造方法传递和setter方法传递。
在实际编程中,我们一般需要做到以下三点:
- 低层模块尽量都要有抽象类或接口,或者两者都有。
- 变量的声明类型尽量是抽象类或接口。
- 使用继承时遵循里氏代换原则。
五、接口隔离原则
定义;使用多个小的专门的接口,而不要使用一个大的总接口。
注意:
- 接口尽量小,但是要有限度,对接口进行细化可以提高程序设计灵活性是不争的事实,但是如果过小,则会造成接口数量过多,使设计复杂化,所以一定要适度。
- 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来,只有专注的为一个模块提供定制服务,才能建立最小的依赖关系。
- 提高内聚,减少对外交互,使接口用最少的方法去完成最多的事情。
六、迪米特法则
定义:一个软件实体应当尽可能少的与其他实体发生相互作用。
迪米特法则又叫最少知道原则,通俗的来讲,就是一个类对自己依赖的类知道的越少越好,也就是说,对于被依赖的类来说,无论逻辑多么复杂,都尽量的将逻辑封装在类的内部,对外除了提供的public方法,不对外泄漏任何信息。
迪米特法则还有几种定义形式,包括:不要和“陌生人”说话,只与你的直接朋友通信等。在应用迪米特法则时,一个对象只能与直接朋友发生交互,不要与“陌生人”发生直接交互,这样做可以降低系统的耦合度,一个对象的改变不会给太多其他对象带来影响。