设计模式
一个合格软件工程师,必备技能
问题引入
- 软件设计中普遍出现的问题,该有何种解决方案?
- 项目开发完成后,客户提出新功能怎么办?(可扩展性,使用设计模式来提高扩展性)
- 如果需要接手维护项目该怎么办?如何使项目可读性强,具有规范性?
- 大厂要求掌握设计模式
- 软件编写过程中出现耦合性高,内聚性低,可维护性差,可扩展性差,重用性差,灵活性低等问题
设计模式目标
提高⬇
- 代码重用性(即:相同功能的代码,不用多次编写)
- 可读性(即:代码规范性,便于其他程序员阅读)
- 可扩展性(即:增加新功能时方便,也称为可维护性)
- 可靠性(即:新增功能后,对原来的功能没有影响)
- 使程序呈现高内聚(模块内部紧密),低耦合(模块和模块之间,功能和功能之间依赖性很低)特性
设计模式七大原则
基础
(即:设计模式为什么这样设计的依据)1. 单一职责原则
2. 接口隔离原则
3. 依赖倒置原则
4. 里氏替换原则
5. 开闭原则
6. 迪米特法则
7. 合成复用原则
设计模式在哪?
面向对象(oo)=>功能模块[设计模式+算法(数据结构)]=>框架[使用到多种设计模式]=>架构[服务器集群]
一、单一职责
介绍
对类来说,一个类应该只负责一项职责.
如类A负责两个不同的职责A、B,如果需修改职责A从而修改类A,但是导致职责B执行错误,就不符合单一职责原理.
代码解释(也可跳过)
目标: 实现摩托车、汽车在公路上运行,飞机在空中运行,轮船在水中运行的效果
Vehicle vehicle=new Vehicle();
vehicle.run("摩托车");
vehicle.run("轮船");
vehicle.run("汽车");
vehicle.run("飞机");
//方案一
// 交通工具类
class Vehicle{
public void run(String vehicle){
System.out.println(vehicle+"在公路上运行...");
}
}
/*在方案1中的run方法中,违反了单一职责原则
* 解决方案非常简单,根据交通工具运行方式不同分解成不同的类=>方案二*/
//方案二
class RoadVehicle{
public void run(String vehicle) {
System.out.println(vehicle+"在公路运行");
}
}
class AirVehicle{
public void run(String vehicle) {
System.out.println(vehicle+"在空中运行");
}
}
class WaterVehicle{
public void run(String vehicle) {
System.out.println(vehicle+"在水中运行");
}
}
/*方案二遵守了单一原则
* 缺点:改动很大,将类分解,同时修改客户端
* 改进:直接修改Vehicle类,改动代码较少=>方案三*/
//方案三
//1.这种修改方法没有对原来的类做大的修改,只是增加方法
//2.类级别上没有遵守单一原则,但是方法级别上实现了单一原则
class Vehicle2{
public void run(String vehicle){
System.out.println(vehicle+"在公路上运行...");
}
public void runAir(String vehicle){
System.out.println(vehicle+"在空中上运行...");
}
public void runWater(String vehicle){
System.out.println(vehicle+"在水中上运行...");
}
}
注意事项、细节
- 降低类的复杂度,一个类只负责一项职责.
- 提高类的可读性,可维护性
- 降低变更引起的风险
- 通常情况下,应遵守单一职责原则,但是只要逻辑够简单,可以在代码级违反单一职责原则(即:方案三的方法级别上的实现单一职责)
二、接口隔离原则
介绍
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。
UML图
- 代表B,D实现了Interface1接口
- A通过Interface1依赖B并使用其1,2,3方法
- C通过Interface1依赖D并使用其1,4,5方法
代码解释
//1.创建一个接口类interface1
interface Interface1 {
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
//2.创建实现接口的B类
class B implements Interface1 {
public void operation1() {
System.out.println("B 实现了operation1");
}
public void operation2() {
System.out.println("B 实现了operation2");
}
public void operation3() {
System.out.println("B 实现了operation3");
}
public void operation4() {
System.out.println("B 实现了operation4");
}
public void operation5() {
System.out.println("B 实现了operation5");
}
}
//3.创建实现接口的D类
class D implements Interface1 {
public void operation1() {
System.out.println("D 实现了operation1");
}
public void operation2() {
System.out.println("D 实现了operation2");
}
public void operation3() {
System.out.println("D 实现了operation3");
}
public void operation4() {
System.out.println("D 实现了operation4");
}
public void operation5() {
System.out.println("D 实现了operation5");
}
}
//4.A类的实现
class A { //A通过接口interface1依赖B类只想使用1,2,3
public void depend1(Interface1 interface1) {
interface1.operation1();
}
public void depend2(Interface1 interface1) {
interface1.operation2();
}
public void depend3(Interface1 interface1) {
interface1.operation3();
}
}
//5.C类的实现
class C { //C通过接口interface1依赖D类只想使用1,4,5
public void depend1(Interface1 interface1) {
interface1.operation1();
}
public void depend4(Interface1 interface1) {
interface1.operation4();
}
public void depend5(Interface1 interface1) {
interface1.operation5();
}
}
- 从定义出发,一个类对另一个类的依赖应该建立在最小的接口上
- 类A通过接口Interface1依赖类B,但是类B需要去实现类A不需要的方法,在不符合接口隔离原则
- 同理类C
处理
将接口Interface1拆分成为独立的几个接口,类A和类C分别与他们所需要的接口建立依赖关系.
public class Segregation2 {
public static void main(String[] args) {
A a = new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
C c= new C();
c.depend1(new D());
c.depend4(new D());
c.depend5(new D());
}
}
interface Interface1 {
void operation1();
}
interface Interface2 {
void operation2();
void operation3();
}
interface Interface3 {
void operation4();
void operation5();
}
class B implements Interface1, Interface2 {
public void operation1() {
System.out.println("B 实现了operation1");
}
@Override
public void operation2() {
System.out.println("B 实现了operation2");
}
@Override
public void operation3() {
System.out.println("B 实现了operation3");
}
}
class D implements Interface1, Interface3 {
public void operation1() {
System.out.println("D 实现了operation1");
}
@Override
public void operation4() {
System.out.println("D 实现了operation4");
}
@Override
public void operation5() {
System.out.println("D 实现了operation5");
}
}
class A { //A通过接口interface1依赖B类只想使用1,2,3,依赖interface1,interface2
public void depend1(Interface1 interface1) {
interface1.operation1();
}
public void depend2(Interface2 interface1) {
interface1.operation2();
}
public void depend3(Interface2 interface1) {
interface1.operation3();
}
}
class C { //C通过接口interface1依赖D类只想使用1,4,5,依赖interface1,interface3
public void depend1(Interface1 interface1) {
interface1.operation1();
}
public void depend4(Interface3 interface1) {
interface1.operation4();
}
public void depend5(Interface3 interface1) {
interface1.operation5();
}
}