设计模式和设计原则-中高级架构思路-面向接口编程

作者:自由生长2024日期:2025/12/31

历史文章参见

设计模式-23种设计模式的说法-掘金

每日知识-设计模式-状态机模式-掘金

每日知识-设计模式-观察者模式 - 掘金

cpp笔记第3篇-C++多线程单例模式单例模式 - 掘金


今天讲讲面向接口编程的核心思想,它可以看到各种设计模式的一种杂糅。

面向接口编程的核心思想

以实际的代码举例子,我最近在写一个安卓的笔记程序,使用到了面向接口的编程方法,下面我以具体的类举例来说明面向接口编程的思想,以及后文解释,面向接口编程可以体现哪些设计模式。

一、依赖接口,而不是具体实现

1//  面向具体类(耦合)
2public class NoteListManager {
3    private MainActivity activity; // 直接依赖 MainActivity
4}
5
6//  面向接口(解耦)
7public class NoteListManager {
8    private INoteListCallback callback; // 依赖接口
9    // 优势:只要接口不变,实现类怎么变都行
10}
11

二、在这个场景中的体现

1. 定义接口(契约)
1// INoteListCallback.java - 定义"契约"
2public interface INoteListCallback {
3    // 定义需要什么方法,不关心怎么实现
4    String formatTimestamp(long timestamp);
5    int dpToPx(int dp);
6    NoteDbHelper getDbHelper();
7}
8
2. 实现接口(具体实现)
1// MainActivity.java - 实现接口
2public class MainActivity implements INoteListCallback {
3    // 提供具体实现
4    @Override
5    public String formatTimestamp(long timestamp) {
6        // 具体怎么格式化,MainActivity 自己决定
7    }
8}
9
3. 使用接口(依赖抽象)
1// NoteListManager.java - 只依赖接口
2public class NoteListManager {
3    private INoteListCallback callback; // 只依赖接口,不依赖具体类
4    
5    public void displayNote(Note note) {
6        // 通过接口调用,不知道具体是哪个类实现的
7        String time = callback.formatTimestamp(note.getTimestamp());
8    }
9}
10

三、面向接口编程的优势

1. 解耦
1// NoteListManager 不知道 MainActivity 的存在
2// 它只知道有一个对象实现了 INoteListCallback 接口
3// 可以是 MainActivity,也可以是 TestActivity,也可以是 MockActivity
4
2. 可测试性
1// 测试时,可以用 Mock 实现
2class MockCallback implements INoteListCallback {
3    @Override
4    public String formatTimestamp(long timestamp) {
5        return "Mock时间"; // 测试用的简单实现
6    }
7}
8
9// 测试 NoteListManager
10NoteListManager manager = new NoteListManager();
11manager.initialize(listView, new MockCallback()); //  Mock 测试
12
3. 可扩展性
1// 以后可以有不同的实现
2class AnotherActivity implements INoteListCallback {
3    @Override
4    public String formatTimestamp(long timestamp) {
5        return "另一种格式"; // 不同的实现方式
6    }
7}
8
9// NoteListManager 不需要改,只需要传入不同的实现
10manager.initialize(listView, new AnotherActivity());
11

四、设计原则体现

1. 依赖倒置原则(DIP)
1高层模块(NoteListManager)不应该依赖低层模块(MainActivity)
2两者都应该依赖抽象(INoteListCallback)
3
2. 开闭原则(OCP)
1对扩展开放:可以添加新的实现类
2对修改关闭:NoteListManager 不需要修改
3

五、优点总结

1面向接口编程 = 定义接口(契约)
2            = 实现接口(具体实现)
3            = 使用接口(依赖抽象)
4            = 解耦、可测试、可扩展
5

Callback 就是面向接口编程思想的实际体现。下面我们看看哪些具体的设计模式都跟面向接口编程有关。

与面向接口编程有关的设计模式

常见的一种是策略模式。当然,面向接口编程不仅体现在策略模式中,还贯穿于多种行为型和结构型模式

一、在行为型模式中的体现

1. 观察者模式(Observer) ⭐️ 高度体现

1// 定义接口
2interface Observer {
3    void update(String message);
4}
5
6interface Subject {
7    void registerObserver(Observer o);
8    void removeObserver(Observer o);
9    void notifyObservers();
10}
11
12// 实现接口
13class User implements Observer {
14    @Override
15    public void update(String message) {
16        System.out.println("收到消息: " + message);
17    }
18}
19
20// 使用接口
21NewsPublisher publisher = new NewsPublisher();
22publisher.registerObserver(new User());  // 依赖接口,不依赖具体类
23

接口思维:Observer是观察者的抽象,Subject是主题的抽象。双方通过接口通信。

2. 命令模式(Command) ⭐️ 核心就是接口

1// 定义命令接口
2interface Command {
3    void execute();
4    void undo();
5}
6
7// 不同实现
8class SaveCommand implements Command {
9    @Override
10    public void execute() {
11        // 保存逻辑
12    }
13}
14
15class DeleteCommand implements Command {
16    @Override
17    public void execute() {
18        // 删除逻辑
19    }
20}
21
22// 使用命令
23Button saveBtn = new Button(new SaveCommand());  // 传入接口
24

接口思维:将请求封装为对象,所有命令都实现Command接口,调用者只依赖接口。

3. 状态模式(State)

每日知识-设计模式-状态模式- 掘金

1interface State {
2    void handle(Context context);
3}
4
5class ConcreteStateA implements State {
6    @Override
7    public void handle(Context context) {
8        context.setState(new ConcreteStateB());  // 切换到另一个状态
9    }
10}
11

接口思维:状态抽象为接口,上下文对象依赖State接口而不是具体状态。

4. 模板方法模式(Template Method)

1abstract class DataProcessor {
2    // 模板方法 - 定义算法骨架
3    public final void process() {
4        readData();      // 固定步骤
5        transformData(); // 抽象方法,子类实现
6        saveData();      // 固定步骤
7    }
8    
9    // 抽象方法 - 通过实现来变化
10    protected abstract void transformData();
11}
12

接口思维:虽然用抽象类,但思想一致 - 定义算法框架,具体步骤由子类实现。

二、在结构型模式中的体现

1. 适配器模式(Adapter) - 核心是统一接口

1// 目标接口(期望的接口)
2interface MediaPlayer {
3    void play(String audioType, String fileName);
4}
5
6// 已有的类,接口不兼容
7class Mp4Player {
8    public void playMp4(String fileName) { /*...*/ }
9}
10
11// 适配器 - 实现目标接口,包装已有类
12class Mp4Adapter implements MediaPlayer {
13    private Mp4Player mp4Player;
14    
15    @Override
16    public void play(String audioType, String fileName) {
17        if (audioType.equals("mp4")) {
18            mp4Player.playMp4(fileName);  // 适配
19        }
20    }
21}
22

接口思维:通过适配器统一不同系统的接口,客户端只依赖MediaPlayer接口。

2. 桥接模式(Bridge) - 抽象与实现分离

1// 抽象部分
2abstract class Shape {
3    protected Color color;  // 桥接 - 组合Color接口
4    
5    public Shape(Color color) {
6        this.color = color;
7    }
8    
9    abstract void draw();
10}
11
12// 实现部分接口
13interface Color {
14    String fill();
15}
16
17// 具体实现
18class Red implements Color {
19    @Override
20    public String fill() {
21        return "红色";
22    }
23}
24
25// 使用
26Shape circle = new Circle(new Red());  // 通过接口组合
27

接口思维:将抽象(Shape)与实现(Color)解耦,通过接口组合。

3. 代理模式(Proxy)

1interface Image {
2    void display();
3}
4
5class RealImage implements Image {
6    @Override
7    public void display() {
8        // 实际加载图片
9    }
10}
11
12class ProxyImage implements Image {  // 代理类也实现相同接口
13    private RealImage realImage;
14    
15    @Override
16    public void display() {
17        if (realImage == null) {
18            realImage = new RealImage();  // 延迟加载
19        }
20        realImage.display();
21    }
22}
23

接口思维:代理类和真实类实现相同的接口,客户端无感知。

三、在创建型模式中的体现

1. 工厂方法模式(Factory Method)

1interface Product {
2    void use();
3}
4
5interface Creator {
6    Product createProduct();  // 工厂方法 - 返回接口
7}
8
9class ConcreteCreator implements Creator {
10    @Override
11    public Product createProduct() {
12        return new ConcreteProduct();  // 返回具体产品,但声明为Product接口
13    }
14}
15

接口思维:工厂返回接口类型,客户端不依赖具体产品类。

2. 抽象工厂模式(Abstract Factory)

1interface GUIFactory {
2    Button createButton();
3    Checkbox createCheckbox();
4}
5
6interface Button {
7    void paint();
8}
9
10// 客户端代码
11class Application {
12    private Button button;
13    
14    public Application(GUIFactory factory) {  // 依赖工厂接口
15        button = factory.createButton();
16    }
17}
18

接口思维:整套产品族通过接口定义,具体工厂实现接口。

四、面向接口编程的层次

第一层:技术实现

1// 简单的接口定义与实现
2interface A { void doSomething(); }
3class B implements A { ... }
4

第二层:设计模式

1// 模式级别的接口应用
2// 1. 策略模式:定义算法族,使其可以互换
3// 2. 观察者模式:定义发布-订阅的通信机制
4// 3. 命令模式:将请求封装为对象
5// 4. 状态模式:将状态抽象为接口
6

第三层:架构思想

1// 系统架构层面的接口
2// - 依赖倒置:高层模块不依赖低层模块,都依赖抽象
3// - 接口隔离:多个专用接口优于一个通用接口
4// - 六边形架构:通过端口(接口)与外部世界通信
5

五、实际项目中的应用启示

何时选择哪种模式?

场景适合的模式接口的作用
算法可互换策略模式定义算法接口
对象状态变化状态模式定义状态接口
请求需要封装命令模式定义命令接口
解耦通知机制观察者模式定义观察者接口
统一不同接口适配器模式定义目标接口
延迟/控制访问代理模式定义主体接口

一个综合示例:电商订单系统

1// 策略模式:不同的折扣策略
2interface DiscountStrategy {
3    double calculateDiscount(Order order);
4}
5
6// 状态模式:订单状态
7interface OrderState {
8    void next(Order order);
9    void previous(Order order);
10    void process(Order order);
11}
12
13// 观察者模式:订单状态通知
14interface OrderObserver {
15    void update(Order order);
16}
17
18// 命令模式:订单操作
19interface OrderCommand {
20    void execute();
21    void undo();
22}
23

总结

面向接口编程是贯穿所有设计模式的灵魂思想

  1. 策略模式:最直接的体现,但远不止于此
  2. 行为型模式中大部分都基于接口:
    • 观察者、命令、状态、策略等核心都是接口抽象
  3. 结构型模式通过接口实现结构解耦:
    • 适配器统一接口,桥接分离抽象与实现
  4. 创建型模式通过接口隐藏创建细节

核心思想:面向接口编程不仅仅是写一个interface,而是:

  • 依赖抽象,而不是具体
  • 定义契约,而不是实现
  • 关注能做什么,而不是怎么做

这在GoF的23种设计模式中都有深刻体现,是面向对象设计的精髓所在。


设计模式和设计原则-中高级架构思路-面向接口编程》 是转载文章,点击查看原文


相关推荐


你以为 Props 只是传参? 不,它是 React 组件设计的“灵魂系统”
白兰地空瓶2025/12/22

90% 的 React 初学者,都低估了 Props。 他们以为它只是“从父组件往子组件传点数据”。 但真正写过复杂组件、设计过通用组件的人都知道一句话: Props 决定了一个组件“好不好用”,而不是“能不能用”。 这篇文章,我们不讲 API 清单、不背概念, 而是围绕 Props 系统的 5 个核心能力,一次性讲透 React 组件化的底层逻辑: Props 传递 Props 解构 默认值(defaultProps / 默认参数) 类型校验(PropTypes) children 插


前端跨页面通讯终极指南⑥:SharedWorker 用法全解析
一诺滚雪球2025/12/14

前言 前面的文章已经介绍了postMessage、localStorage、messageChannel、broadcastChannel以及window.name。今天要介绍一种“多页面协同”场景的工具——SharedWorker。 不同于普通Worker只能被单个页面独占,SharedWorker能被同一域名下的多个页面共享,实现高效的“多页面数据中枢”。本文就带你了解SharedWorker跨页面通讯的核心用法。 1. 什么是SharedWorker? 在介绍SharedWorker之前,


从 Oracle 到 KingbaseES:破解迁移痛点,解锁信创时代数据库新可能
倔强的石头_2025/12/5

提起 Oracle,它在传统数据库领域可是标杆般的存在,长久以来一直撑起了众多企业的核心业务,可这两年情形发生了改变,Oracle的授权费用很高,运维成本又让人头疼,再加上信创政策对于合规有着强硬的要求,于是很多企业便开始把目光转向国产数据库。金仓数据库 KingbaseES 是国产数据库中的佼佼者,凭借其高适配性和高性能的基础,成了人们更换 Oracle 的首要选择,不过要告诉大家的是,迁移之路并非易走,“报错”频繁出现,存在适配性障碍,成本难以控制住……这些难点真真切切地成为了企业在执行迁移


HarmonyOS一杯冰美式的时间 -- FullScreenLaunchComponent
猫猫头啊2026/1/9

一、前言 最近在开发中,我们的元服务需要被其他应用通过FullScreenLaunchComponent拉起,我只能说当时上了5.0的当,FullScreenLaunchComponent也是Beta版本的!在实际开发中作为碰了几次灰,踩了不少坑,觉得有必要分享下,故有了此篇文章。 该系列依旧会带着大家,了解,开阔一些不怎么热门的API,也可能是偷偷被更新的API,也可以是好玩的,藏在官方文档的边边角角~当然也会有一些API,之前是我们辛辛苦苦的手撸代码,现在有一个API能帮我们快速实现的,希望


Monorepo入门
Hyyy2026/1/17

1. Monorepo 介绍 核心价值:把“需要一起演进的一组项目”放在同一个版本空间里,从而让跨项目改动(API 变更、重构、升级)能在一次提交里完成并验证 Monorepo 是把多个相关项目/包放在同一个 Git 仓库中管理的策略,有助于跨项目联动修改、内部包共享更顺畅、统一规范与 CI、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性。 Monorepo 提倡了开放、透明、共享的组织文化,这种方法已经被很多大型公司广泛使用,如 Google、Facebook 和 Mic


墨梅博客 1.2.0 发布与 AI 开发实践 | 2026 年第 4 周草梅周报
草梅友仁2026/1/25

本文在 草梅友仁的博客 发布和更新,并在多个平台同步发布。如有更新,以博客上的版本为准。您也可以通过文末的 原文链接 查看最新版本。 前言 欢迎来到草梅周报!这是一个由草梅友仁基于 AI 整理的周报,旨在为您提供最新的博客更新、GitHub 动态、个人动态和其他周刊文章推荐等内容。 开源动态 本周依旧在开发 墨梅 (Momei) 中。 您可以前往 Demo 站试用:demo.momei.app/ 您可以通过邮箱 admin@example.com,密码momei123456登录演示用管理


上下文工程(Context Engineering)
uzong2026/2/4

本文整理自 LangChain 博客《Context Engineering for Agents》」更自然 blog.langchain.com/context-eng… 随着大语言模型(LLM)在智能体(Agent)系统中的广泛应用,如何有效管理有限的上下文窗口(Context Window)成为关键挑战。 1. 为什么需要上下文工程? 大语言模型的上下文窗口类似于计算机的 RAM——它是模型的“工作记忆”,但容量有限。当智能体执行长期任务时,会不断累积以下类型的上下文: ● 指令(Inst


【C++】多态
yuuki2332332026/2/12

前言: 在面向对象编程的学习脉络中,继承机制让代码的复用和层级设计成为可能,但仅靠继承无法完全体现对象行为的灵活性。比如我们通过继承定义了Person基类,以及Student、Soldier等派生类后,若想让不同对象执行 “买票” 这一相同名称的行为时展现出不同逻辑(普通人全价、学生打折、军人优先),单纯的继承语法无法高效实现这种 “一个接口,多种实现” 的需求。而多态作为继承的延伸与升华,恰好解决了这一问题 —— 它让继承体系下的不同对象,对同一行为能做出符合自身特性的响应,是面向对象编程中实


基于 YOLOv8 的水体污染目标检测系统 [目标检测完整源码]
我是杰尼2026/2/21

基于 YOLOv8 的水体污染目标检测系统 [目标检测完整源码] 一、背景:水体监控为什么需要“计算机视觉”? 在水资源保护与环境治理领域,“看得见问题”往往是治理的第一步。然而在真实场景中,水体监控长期面临以下现实挑战: 水域面积大、人工巡检成本高 污染物种类多、形态变化大 人工判读主观性强、难以量化 传统传感器难以识别“视觉型污染” 随着无人机、高清摄像头、遥感设备的普及,水体数据获取已不再是瓶颈,真正的难点转移到了如何从海量影像中自动识别污染风险。 基于此,本文介绍一套 以 YOLOv


OpenClaw安装技能的三种方式
可夫小子2026/3/1

OpenClaw安装技能的三种方式 💡 大家好,我是可夫小子,《小白玩转ChatGPT》专栏作者,关注AI编程、AI自动化和自媒体。 OpenClaw很强大,但也需要搭配很多技能才能发挥最大的作用,它的安装方式没有像Claude Code那样复杂,但也还有一些操作过程。在OpenClaw里面,可以通过WebUI的界面,很直观的管理安装的技能。 但如果安装技能呢?今天分享常用的三种方式。 通过官方openclaw命令来配置 通过openclaw config 命令,选择Local→Ski

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客