设计模式 · 外观模式(Facade Pattern)java
设计模式 · 外观模式(Facade Pattern)前言在日常开发中,我们经常会遇到这样一类代码:业务目标本身很简单,但为了完成它,客户端不得不依次调用很多底层类。
以本项目为例,客户端只是想把一个视频文件转换成指定格式。但如果直接使用底层媒体处理库,就需要自己完成加载视频、识别源编码器、选择目标编码器、读取码率、执行转换、修复音频等一整套流程。
这类问题的核心不是“代码能不能跑”,而是“调用者是否被迫理解太多细节”。
外观模式正是为了解决这种复杂调用暴露给客户端的问题。
图片来自:外观设计模式(门面模式)
一、核心定义外观模式(Facade Pattern)是一种结构型设计模式。
它为复杂子系统提供一个统一、简洁的高层接口,让客户端通过这个接口完成操作,而不需要直接依赖子系统中的多个类。
可以把它理解成:
外观类负责把复杂流程组织好,客户端只调用一个简单方法。
**举例来说:**当你通过电话给商店下达订单时, 接线员就是该商店的所有服务和部门的外观。 接线员为你提供了一个同购物系统、 支付网关和各种送货服务进行互动的简单语音接口。
外观模式的目标不是替代子系统,也不是隐 ...
使用苹果设备与礼品卡充值ChatGPT Plus(土耳其区)详细教程
使用苹果设备与礼品卡充值ChatGPT Plus(土耳其区)详细教程前言充值chatgpt会员在国内有些门槛。在实际操作中,很多朋友都被网页版严苛的信用卡风控(Stripe拦截)拒之门外。
别慌,这条大路走不通,我们可以走“VIP侧门”:
利用iPhone或iPad的苹果生态,搭配土耳其区Apple ID和苹果商店礼品卡,实现曲线救国。
这篇笔记将带你由浅入深,彻底打通这条极具性价比的充值链路。
一、 核心原理与底层逻辑1.1 概念拆解:什么是“曲线救国”?我们可以打个比方:网页版ChatGPT直接绑卡,需要海外信用卡。gpt几乎是所有国外AI会员中绑卡验证最严的。
而使用iOS客户端充值,则是让“苹果公司”这个德高望重的大佬出面担保。只要你的Apple ID钱包里有钱,苹果就会帮你代扣款。
ChatGPT一看是苹果大佬结账,直接放行。
1.2 为什么选择“土耳其区”?全球各大应用商店存在“汇率差”。
由于土耳其里拉的汇率波动,土耳其区的苹果商店订阅价格通常是全球数字洼地。
网页版充值需要20美元,折合人民币140,但是一个新的chatgpt账号充值,在土耳其区充值这和人民币只需要80 ...
Git 提交与推送常见报错处理笔记
Git 提交与推送常见报错处理笔记前言在日常开发中,git commit 和 git push 看似简单,但经常会遇到提交失败、推送被拒绝等问题。
本文整理两个常见场景:提交时被 ESLint 拦截,以及推送时出现 non-fast-forward 报错。
一、提交时被 ESLint 拦截1.1 报错现象执行提交命令:
1git commit -m "邮箱后缀已去除"
出现类似信息:
123Running ESLint on web moduleeslint --fix [FAILED]husky - pre-commit script failed
并提示某些文件存在未使用变量:
12error Remove this useless assignment to variable "router"error Remove this useless assignment to variable "docLink"
如图所示:
1.2 报错原因这不是 Git 本身报错,而是项目配置了提交前检查。
常见流程是:
12345 ...
设计模式-装饰器模式(java)
设计模式-装饰器模式(java)前言装饰器模式(Decorator Pattern)属于结构型设计模式。它的核心思想是:在不修改原有对象结构的前提下,通过包装对象,为原对象动态增加额外职责。
它解决的不是“能不能加功能”的问题,而是“如何在不破坏原有代码稳定性的前提下,把新功能优雅地加上去”的问题。
装饰器模式的典型认知误区:遇到”需要给某个已有类增加功能”时,第一反应总是继承——继承后重写方法,把新逻辑写进去。这在功能单一、不再迭代的场景下没有问题,但一旦需要横向扩展多种功能,就会催生出大量子类,最终维护成本失控。
装饰器模式提供了另一条路:不改变原有类,不继承原有类,而是用一个”包装类”在运行时动态叠加新功能。
本文代码案例:https://github.com/likerhood/CodeDesignWork/tree/main/codedesign8.0-0 和 8.0-1 、8.0-2
一、核心定义装饰器模式,也叫 Decorator、Wrapper,是一种通过“组合”替代“继承”来扩展对象行为的模式。
它的核心定义可以拆成三句话理解:
装饰器和被装饰对象实现同一个接 ...
设计模式 · 组合模式(Composite Pattern)
设计模式 · 组合模式(Composite Pattern)前言随着业务线的发展,系统中的判断逻辑变得越来越错综复杂。
今天产品要求“按性别发不同的优惠券”,明天要求“加上年龄段限制”,后天又追加了“新老用户身份”。
如果用传统的编程思维,这段代码很快就成为一座由无限嵌套 if-else 构成的“屎山”。
面对这种易变的规则嵌套,有没有一种优雅的设计能够打破僵局?
组合模式(Composite Pattern) 给出了完美的答案。
它通过将独立的业务逻辑抽象为原子节点,并像搭积木一样组合成一棵“决策树”,最精妙的是,它让外部调用方可以无差别地处理单个节点和复杂的树形结构。
组合模式在实际业务中的经典场景:不同类型的决策节点(身份证校验、银行卡校验、手机号校验)可以自由组合成一棵服务树,不同调用方使用不同的树结构,而无需修改任何节点代码。
本文代码链接:https://github.com/likerhood/CodeDesignWork/tree/main/codedesign7.0-0 和7.0-1
一、核心定义组合模式(Composite Pattern)是一种用来组织“树 ...
Java 访问修饰符:public、protected、private讲解
Java 访问修饰符:public、protected、private讲解前言Java 提供的四种访问修饰符(private、默认(包私有)、protected、public)。
一、四种访问级别总览1.1 一张表总结Java 共有四种访问级别,其中三种有关键字,一种是默认(不写任何修饰符):
访问级别
关键字
可访问范围
私有
private
仅本类内部
默认(包私有)
(不写)
本类 + 同包的类
受保护
protected
本类 + 同包的类 + 子类(跨包也可)
公开
public
任何地方
1.2 可见性矩阵
访问位置
private
默认
protected
public
本类
✓
✓
✓
✓
同包其他类
✗
✓
✓
✓
不同包子类
✗
✗
✓
✓
不同包无关类
✗
✗
✗
✓
二、private :封装的基石2.1 核心作用private 是封装的直接体现:把实现细节藏起来,只暴露必要的接口。
12345678910111213141516171819public class BankAccount { ...
设计模式 · 桥接模式(Bridge Pattern)java
设计模式 · 桥接模式(Bridge Pattern)java前言业务代码里大量 if-else,往往不是因为逻辑复杂,而是因为变化维度被写死在了一起。
以支付场景为例,支付渠道可能有微信、支付宝、银联,支付模式又可能有密码、刷脸、指纹。如果把这些组合都写进一个方法里,短期看实现很快,长期看每新增一种渠道或模式,都要改动原有代码,重复逻辑越来越多,维护成本也越来越高。
桥接模式要解决的正是这类问题:当系统中存在两个或多个可以独立变化的维度时,将它们拆分出来,通过组合建立连接,避免类数量和判断分支随着组合关系膨胀。
本文将以“支付渠道 × 支付模式”为例,讲解桥接模式如何把复杂的组合逻辑拆成清晰、可扩展的面向对象结构。
本文代码链接:https://github.com/likerhood/CodeDesignWork/tree/main/codedesign6.0-0 和6.0-1
一、核心定义桥接模式(Bridge Pattern) 是一种结构型设计模式,将抽象部分与实现部分分离,使它们可以独立变化。
核心机制:在抽象类 A 中持有实现接口 B 的引用,通过构造函数由外部传 ...
Claude Code 技术中的 Prompt Caching 学习笔记
Claude Code 技术中的 Prompt Caching 学习笔记前言Claude Code 这类编程 Agent 为什么能在长上下文、多轮对话、频繁工具调用中保持相对可用的速度和成本?一个关键答案是:Prompt Caching。
它并不是简单地缓存模型回答,而是缓存模型处理稳定 prompt 前缀时产生的中间状态,让后续请求不必反复计算相同的系统提示、工具定义、项目文档和历史上下文。
本文会从大模型的 token 生成机制讲起,逐步解释 KV Cache、Prompt Caching 以及它们之间的关系,再梳理 Claude Code 如何通过 prompt 编排、工具设计、模型选择和上下文压缩来提高缓存命中率。
最后也会讨论一个现实问题:如果把 Claude Code 底层模型换成其他模型或 API,缓存机制是否还会生效。
一、理解基础:大模型如何处理输入和生成输出1.1 大模型处理的是 token,不是直接处理文字我们平时看到的是自然语言文本,比如:
请帮我解释这段代码
但模型真正接收的不是这句话本身,而是 tokenizer 切分后的 token 序列。
1.1. ...
学习ConcurrentHashMap使用和并发基础(java)
学习ConcurrentHashMap使用和并发(java)前言
参考学习视频链接:带你透彻理解ConcurrentHashMap,最新最全的面试题及解答_哔哩哔哩_bilibili
一、 为什么用ConcurrentHashMap1.1 什么是 ConcurrentHashMap简单来说,ConcurrentHashMap 是 Java 并发包(java.util.concurrent)中提供的一个线程安全的高效哈希表。
它的核心功能和 HashMap 一样,都是用来存储键值对(Key-Value)数据的,但它允许多个线程同时对它进行读写操作而不会把数据搞乱。
在单线程的 HashMap 中,key 和 value 都允许为 null。但在ConcurrentHashMap中,key 和 value 绝对不能为 null。
原因: 这是为了防范并发环境下的“二义性(歧义)”问题。如果 get(key) 返回了 null,你根本无法确认是“这个 key 不存在”,还是“这个 key 的 value 被设置成了 null”。在单线程中,你可以通过 containsKey(key) ...
Java 动态代理深度解析:从"为什么"到"底层原理"
Java 动态代理深度解析:从”为什么”到”底层原理”前言你有没有思考过一个问题:在 MyBatis 中,你只写了一个 UserMapper 接口,从来没有写过它的实现类,却可以直接调用 userMapper.selectById(1) 查出数据库结果?
这背后隐藏的技术叫做 JDK 动态代理,它是 Java 反射机制的核心应用之一,也是 MyBatis、Spring AOP、RPC 框架的基石。本文将从”为什么需要它”出发,逐步深入到底层字节码原理,并附上可运行的完整代码。
本文运行代码链接:https://github.com/likerhood/CodeDesignWork/tree/main/codedesign0.0-0/src/main/java/com/likerhood/design/mybatisproxy
一、为什么需要动态代理?1.1 先从一个真实问题说起你每天都在用 MyBatis,但有没有想过这段代码为什么能运行?
123456// UserMapper.java —— 只有接口,没有任何实现类public interface UserMapper ...









