SOLID设计原则

java中的solid设计原则
 

SOLID 是**面向对象设计(OOD)**中最经典的五大设计原则,由 Robert C. Martin(Uncle Bob)提出,也是 Java 面试中高频考点。

很多人会背 SOLID,但真正面试时,更重要的是结合实际项目说明如何应用


SOLID 五大原则概览

缩写英文中文核心思想
S Single Responsibility Principle 单一职责原则 一个类只负责一件事
O Open-Closed Principle 开闭原则 对扩展开放,对修改关闭
L Liskov Substitution Principle 里氏替换原则 子类必须能够替换父类
I Interface Segregation Principle 接口隔离原则 接口要小而专一
D Dependency Inversion Principle 依赖倒置原则 面向接口编程,而不是面向实现

下面逐个讲解。


一、S —— 单一职责原则(SRP)

一个类应该只有一个引起它变化的原因。

也就是说:

一个类只负责一项职责。


错误设计

例如:

 
public class UserService {

    public void login(){}

    public void sendSms(){}

    public void exportExcel(){}

    public void uploadAvatar(){}

    public void createOrder(){}
}
 

这个类负责:

  • 登录
  • 短信
  • 导出
  • 上传
  • 下单

明显职责太多。

任何一个功能变化,都可能修改这个类。


正确设计

拆分:

 
LoginService

SmsService

ExportService

FileService

OrderService
 

每个类负责一种业务。

这样:

登录改了

不会影响

导出功能。


生产案例

例如:

电商系统:

 
OrderService
 

只负责:

 
创建订单

取消订单

查询订单
 

支付:

 
PayService
 

物流:

 
LogisticsService
 

库存:

 
StockService
 

这样维护起来非常方便。


二、O —— 开闭原则(OCP)

软件实体应该对扩展开放,对修改关闭。

什么意思?

新增功能:

尽量新增代码。

不要:

修改已有代码。


例如支付:

错误:

 
if(channel=="ALI"){

}

else if(channel=="WX"){

}

else if(channel=="PAYPAL"){

}
 

以后:

新增:

Stripe

又要改 if。

违反开闭原则。


正确:

 
interface PayService{

    void pay();
}
 

支付宝:

 
class AlipayService
 

微信:

 
class WechatPayService
 

新增:

 
class PaypalService
 

OrderService

不用改。


Spring 中:

 
@Resource
private PayService payService;
 

或者:

 
Map<String, PayService>
 

都是典型应用。


三、L —— 里氏替换原则(LSP)

所有引用父类的地方,都必须能够透明地替换成子类。

这是多态成立的重要基础。

例如:

 
Animal animal = new Dog();
animal.eat();
 

为什么成立?

因为:

Dog

能够替换

Animal。


为什么 Java 重写有

两同两小一大

就是为了保证:

LSP。

例如:

父类:

 
public Animal get(){}
 

子类:

 
public Dog get(){}
 

允许。

因为:

Dog

就是

Animal。

但是:

 
public Object get(){}
 

不允许。

否则:

别人要 Animal。

你给 Object。

程序就错了。


经典反例

例如:

 
Bird
 

里面:

 
fly()
 

然后:

 
Penguin extends Bird
 

企鹅不会飞。

说明:

继承关系设计错了。

正确:

 
Bird

↓

FlyBird

↓

Penguin
 

或者:

Flyable

接口。


四、I —— 接口隔离原则(ISP)

客户端不应该依赖自己不需要的方法。

接口:

应该:

小。

专。

例如:

错误:

 
Animal{

eat();

run();

fly();

swim();
}
 

狗:

必须实现:

 
fly();
 

明显错误。


正确:

 
Flyable

Runnable

Swimmable

Eatable
 

Dog:

实现:

 
Runnable

Swimmable
 

Bird:

实现:

 
Flyable
 

Java 集合:

就是这样设计的。

 
Collection

↓

List

↓

Set
 

而不是:

一个超级接口。


五、D —— 依赖倒置原则(DIP)

高层模块不应该依赖低层模块,二者都应该依赖抽象。

也就是说:

不要:

 
new AlipayService();
 

而应该:

 
PayService
 

例如:

错误:

 
public class OrderService{

    private AlipayService payService;
}
 

以后:

微信:

银联:

全部改。


正确:

 
public class OrderService{

    private PayService payService;
}
 

Spring:

 
@Resource
private PayService payService;
 

真正运行:

注入:

 
AlipayService

WechatPayService

PaypalService
 

OrderService

完全不知道。

这就是:

IoC

DI

存在的意义。


五大原则之间的关系

 
SRP
│
│ 一个类只负责一种职责
│
├──────────────┐
│              │
▼              ▼
ISP            OCP
接口更小       更容易扩展
│
└───────┐
        ▼
      DIP
依赖抽象,不依赖实现
        │
        ▼
      LSP
子类可以安全替换父类
 

它们并不是彼此独立的,而是相互促进。例如,接口隔离(ISP)和依赖倒置(DIP)通常一起使用,而良好的单一职责(SRP)也会让系统更容易遵循开闭原则(OCP)。


Spring 框架中 SOLID 的体现

Spring 可以说是 SOLID 思想的经典实践:

原则Spring 中的体现
SRP ControllerServiceRepository 分层,各司其职
OCP 新增 Bean、AOP、扩展点(如 BeanPostProcessor)无需修改框架源码
LSP 父接口引用可以指向不同实现,如 DataSourceApplicationContext
ISP 提供大量小接口,如 BeanFactoryResourceLoaderInitializingBean
DIP IoC 容器和依赖注入(@Autowired@Resource)让业务依赖抽象而不是具体实现

面试回答(推荐)

SOLID 是面向对象设计中的五大原则,包括:S(单一职责)O(开闭原则)L(里氏替换)I(接口隔离)D(依赖倒置)。单一职责强调一个类只负责一项职责;开闭原则强调通过新增代码扩展功能,而不是修改已有代码;里氏替换要求子类能够无缝替换父类,是 Java 多态和重写规则的基础;接口隔离要求接口小而专一,避免“胖接口”;依赖倒置要求业务依赖抽象而不是具体实现,这也是 Spring IoC 和依赖注入的核心思想。在实际项目中,例如支付、短信、文件存储等模块,我通常会先定义接口,再通过多个实现类配合 Spring 注入实现扩展,这样既符合开闭原则,也提高了系统的可维护性和可扩展性。

 

posted on 2026-07-21 09:29  日思日睿  阅读(1)  评论(0)    收藏  举报