java值传递非设计模式但深刻影响其实现:工厂需防缓存对象污染,策略不可靠参数重赋值,装饰器须防状态共享,建造者应做防御性拷贝。

Java 的值传递机制本身不是设计模式,但它深刻影响着设计模式的实现效果和使用边界。理解“所有参数都是副本”这一铁律,能帮你避开陷阱、写出更可控的模式代码。
值传递对工厂模式的影响
工厂方法返回对象时,调用方拿到的是新对象引用的副本——这本身是安全的。但要注意:如果工厂内部缓存了可变对象并直接返回其引用,调用方修改该对象状态,就可能意外污染其他使用者。
- 正确做法:工厂返回前做浅拷贝(如 new ArrayList(cachedList))或不可变包装(Collections.unmodifiableList())
- 错误写法:直接返回内部 mutable list 引用,看似省事,实则破坏封装性
策略模式中避免引用误改
策略对象常作为参数传入上下文(Context)。由于传递的是策略引用的副本,你无法在 Context 内部把形参重指向新策略(比如 strategy = new NewStrategy()),这不会改变外部传入的原始引用。
- 若需动态切换策略,应通过 setter 方法显式更新 Context 内部字段,而非依赖参数重赋值
- 策略类自身状态应尽量设为 final 或私有且只读,防止被调用方通过引用副本意外修改
装饰器模式里注意对象状态共享
装饰器构造时通常接收被装饰对象的引用。这个引用是值传递来的副本,但它仍指向堆中同一个对象。因此,装饰器对被装饰对象属性的修改,会反映在所有持有该引用的地方。
- 若希望装饰器完全隔离副作用,应在构造时深拷贝被装饰对象(或仅传入不可变数据)
- 常见实践:装饰器不修改被装饰对象,而是通过组合+委托方式扩展行为,把状态变更限制在装饰器自身内部
建造者模式中规避参数引用泄露
建造者(Builder)的 build() 方法返回最终对象。如果构建过程中 builder 持有外部传入的集合或对象引用,并直接塞进结果对象,那调用方后续修改这些外部对象,就会穿透影响已构建实例。
- 安全做法:在 build() 中对关键引用字段做防御性拷贝(如 new HashSet(inputSet))
- 尤其注意日期(Date)、数组、集合等易变类型,它们的引用副本依然连着同一块堆内存
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











