Java类层级保留抽象,实现下层交互与上层多隔离实例
需要创建多个无静态字段/方法的「指挥类(commander class)」隔离实例,该类整合所有下层类,且下层类需不知晓指挥类的存在以屏蔽实现细节。
首次尝试(违背层级访问原则)
LowerClass1为了和LowerClass2交互,必须访问上层的CentralClass,破坏了「仅上层类可访问下层类,下层类不可访问上层类」的设计原则:
public class CentralClass { public LowerClass1 lowerClass1; public LowerClass2 lowerClass2; } public class LowerClass1 { public void exampleMethod1() { CentralClass.lowerClass2.exampleMethod2(); } } public class LowerClass2 { public void exampleMethod2() { } }
本质是同层级的LowerClass1被迫知晓了上层指挥类的存在。
二次尝试(无法实现多隔离实例)
LowerClass1直接调用LowerClass2的静态方法,虽保留了层级单向访问,但静态方法导致CentralClass无法创建多个隔离实例:
public class CentralClass { public LowerClass1 lowerClass1; } public class LowerClass1 { public void exampleMethod1() { LowerClass2.exampleMethod2(); } } public class LowerClass2 { public static void exampleMethod2() { } }
两种方案均存在问题:要么破坏层级单向访问逻辑,要么因静态关联无法实现多隔离实例。
核心需求:避免使用静态的前提下,保留下层类对上层类的抽象隐藏,同时实现上层类的多隔离实例,需解答:独立类加载器是否可行?有哪些适用的设计模式?
一、适用的设计模式
1. 依赖注入(Dependency Injection)
这是最直接的解决方案:由指挥类(CentralClass)在初始化下层类时,将需要交互的同层级实例注入到目标类中,下层类只持有依赖实例的引用,完全不知道指挥类的存在。
示例代码:
public class CentralClass { private LowerClass1 lowerClass1; private LowerClass2 lowerClass2; public CentralClass() { this.lowerClass2 = new LowerClass2(); // 将LowerClass2实例注入LowerClass1 this.lowerClass1 = new LowerClass1(lowerClass2); } } public class LowerClass1 { private final LowerClass2 lowerClass2; // 通过构造器注入依赖 public LowerClass1(LowerClass2 lowerClass2) { this.lowerClass2 = lowerClass2; } public void exampleMethod1() { lowerClass2.exampleMethod2(); } } public class LowerClass2 { public void exampleMethod2() { } }
每个CentralClass实例都会创建独立的LowerClass1和LowerClass2实例,天然实现隔离,且下层类完全感知不到指挥类的存在。
2. 中介者模式(Mediator Pattern)
定义抽象中介者接口,指挥类作为具体中介者实现该接口,下层类只依赖抽象中介者而非具体指挥类。当下层类需要交互时,通过抽象中介者转发请求,既隐藏指挥类实现,又实现实例隔离。
示例代码:
// 抽象中介者 public interface Mediator { void notify(String sender, String action); } // 指挥类作为具体中介者 public class CentralClass implements Mediator { private LowerClass1 lowerClass1; private LowerClass2 lowerClass2; public CentralClass() { this.lowerClass1 = new LowerClass1(this); this.lowerClass2 = new LowerClass2(this); } @Override public void notify(String sender, String action) { if ("LowerClass1".equals(sender) && "callMethod2".equals(action)) { lowerClass2.exampleMethod2(); } } } public class LowerClass1 { private final Mediator mediator; public LowerClass1(Mediator mediator) { this.mediator = mediator; } public void exampleMethod1() { mediator.notify("LowerClass1", "callMethod2"); } } public class LowerClass2 { public void exampleMethod2() { } }
下层类仅知晓抽象的Mediator接口,每个CentralClass实例对应一套独立的下层类实例,实现完全隔离。
3. 服务定位器模式(Service Locator Pattern)
创建抽象服务定位器,每个指挥类实例持有独立的定位器实例,下层类通过定位器获取所需依赖,无需知晓指挥类。需确保定位器与指挥类实例绑定,避免全局共享。
示例代码:
// 抽象服务定位器 public interface ServiceLocator { <T> T getService(Class<T> serviceClass); } // 指挥类关联的具体服务定位器 public class CentralServiceLocator implements ServiceLocator { private final Map<Class<?>, Object> services = new HashMap<>(); public CentralServiceLocator() { registerService(LowerClass2.class, new LowerClass2()); } @Override public <T> T getService(Class<T> serviceClass) { return serviceClass.cast(services.get(serviceClass)); } private void registerService(Class<?> clazz, Object instance) { services.put(clazz, instance); } } public class CentralClass { private final ServiceLocator serviceLocator; public LowerClass1 lowerClass1; public CentralClass() { this.serviceLocator = new CentralServiceLocator(); this.lowerClass1 = new LowerClass1(serviceLocator); } } public class LowerClass1 { private final ServiceLocator serviceLocator; public LowerClass1(ServiceLocator serviceLocator) { this.serviceLocator = serviceLocator; } public void exampleMethod1() { LowerClass2 lowerClass2 = serviceLocator.getService(LowerClass2.class); lowerClass2.exampleMethod2(); } } public class LowerClass2 { public void exampleMethod2() { } }
每个CentralClass实例对应独立的服务定位器,下层类通过定位器获取同层级实例,完全屏蔽指挥类的存在。
二、独立类加载器的可行性
独立类加载器可以实现隔离,但属于重量级方案,仅适合特殊场景:
- 可行场景:当下层类存在无法修改的静态状态(如第三方依赖),或需要完全隔离类字节码层面的资源时,独立类加载器可为每个指挥类实例加载一套独立的类定义,实现彻底隔离。
- 弊端:类加载器的创建与管理成本高,会增加内存开销,易引发类加载泄漏;不同类加载器加载的类属于不同运行时类型,跨加载器的对象交互需额外处理,复杂度高。
因此,除非有极端隔离需求,优先选择依赖注入、中介者模式等轻量级方案。
内容的提问来源于stack exchange,提问作者Famro Fexl

