Есть несколько очевидных и плохих способов сделать это:
- сделать OrderCancellationService частным классом внутри DrugOrderManager
- поместить OrderCancellationService и DrugOrderManager в один пакет
Другое решение - использовать другой класс, который получит доступ ко всем экземплярам и перенаправит их в соответствующую реализацию. Только этот класс получит доступ ко всему. Сами сервисы получат доступ только к тому, что им предоставляет общий класс. Это далеко не идеально, все еще существует объект «бог», но он ограничен одним объектом и больше нет ограничений на пакеты.
Вот пример, где Factory - это объект, который имеет все экземпляры и 2 Services, ServiceA и ServiceB. ServiceB имеет доступ к ServiceA, но ServiceA не имеет доступа к ServiceB.
в файле Factory. java:
class Factory {
private static Map<Class, Object> INSTANCES = new HashMap<>();
private ServiceA serviceA;
private ServiceB serviceB;
public static void register(Class clazz, Object instance) {
instances.put(clazz, instance);
}
static {
Class.forName("ServiceA");
Class.forName("ServiceB");
serviceA = (ServiceA)(INSTANCES.get(ServiceA.class));
serviceB = (ServiceB)(INSTANCES.get(ServiceB.class));
serviceB.setServiceA(serviceA);
}
}
}
в файле ServiceA. java:
class ServiceA {
private ServiceA INSTANCE = new ServiceA();
private ServiceA() {}
static {
Factory.register(ServiceA.class, INSTANCE);
}
}
В файловой службе B. java:
class ServiceB {
private ServiceB INSTANCE = new ServiceB();
private ServiceA serviceA;
private ServiceB() {}
public setServiceA(ServiceA serviceA) {
this.serviceA = serviceA;
}
static {
Factory.register(ServiceB.class, INSTANCE);
}
}
Возможны и другие реализации с API рефлексии.
Просто сделайте реализацию частной и позвольте интерфейсу быть опубликованным c.
Для меня то, что вы пытаетесь достичь, не стоит усилий.
Что довольно просто сделать, так это по крайней мере, чтобы ВСЯ реализация была полностью частной, и только точка входа службы publi c была доступна через интерфейсы благодаря модулям Java 9. Поскольку любой сервис обычно представляет собой лишь несколько методов publi c на фасаде, это обеспечивает 95% возможностей без неприятных уловок. Конечно, сервис может видеть каждый его интерфейс publi c, но у них нет возможности даже получить доступ к частной реализации.
До Java 9, чтобы сделать реализацию действительно частной, вы можете использовать maven, make interface & модули реализации для всех служб, и модуль реализации будет зависимостью среды выполнения от интерфейса, поэтому любая ссылка на реализацию не удастся во время компиляции, но реализация будет присутствовать во время выполнения.
Шаблон локатора службы, зависимость Инъекция и Spring
Вы можете видеть мой пример как очень грубую реализацию того, что мы часто называем Service Locator или концепцией внедрения зависимостей.
Spring (https://spring.io/ ) является стандартом де-факто для этого в мире Java. Вы должны проверить несколько уроков / тренировок на net, чтобы увидеть, на что он способен.