核心思路是通过私有内部类实现接口并仅暴露接口类型变量,主类只声明接口类型字段(如private Iterator iterator;),不持有具体实现类类型;内部类私有化并在工厂方法中返回接口类型实例,完成向上转型;禁止暴露内部类实例或使其对外可见;对一次性场景可用匿名内部类或Lambda简化。

核心思路是:用私有内部类实现接口,对外只暴露接口类型变量,主类不暴露内部实现细节,也不持有具体内部类类型字段。
主类只声明接口类型字段
避免在主类中定义 InnerClass impl 这样的具体类型字段。应直接使用接口类型作为成员变量,例如:
-
正确写法:
private Iterator iterator;(假设Iterator是外部定义的接口) -
错误写法:
private StringIterator iterator;(暴露了内部类名,破坏封装)
这样主类结构干净,字段语义明确——它持有一个“可迭代的能力”,而非某个具体实现。
内部类私有化 + 接口向上转型
将实现类声明为 private,并在工厂方法中返回其接口类型实例,完成自动向上转型:
- 内部类定义:
private class StringIterator implements Iterator { ... } - 提供接口型获取方法:
public Iterator iterator() { return new StringIterator(); } - 调用方拿到的是
Iterator,完全不知道背后是StringIterator,更不知其依赖主类私有字段(如values[]、pos)
避免内部类泄露到外部作用域
不通过 getter 暴露内部类实例,也不让内部类成为 public 或包级可见:
- 禁止写
public InnerClass getImpl() { return new InnerClass(); } - 禁止在主类外新建内部类实例,如
new Outer().new InnerClass()—— 这会打破封装边界 - 若需多态行为(如不同策略),可用多个私有内部类分别实现同一接口,并由主类逻辑决定返回哪一个
结合匿名内部类简化一次性场景
对无需复用、逻辑简单的接口实现,直接在方法内用匿名内部类,连内部类命名都省去:
- 例如事件回调:
button.addActionListener(new ActionListener() { public void actionPerformed(...) { ... } }); - 或函数式替代(JDK 8+):
button.addActionListener(e -> System.out.println("clicked")); - 既保持主类字段零膨胀,又满足接口契约,代码即写即弃、职责清晰

















