Я читал об этом "Законе Деметры", и он (и вообще чистые классы-обёртки), кажется, вообще анти-паттерны. Рассмотрим класс реализации:
class FluidSimulator {
void reset() { /* ... */ }
}
Теперь рассмотрим две разные реализации другого класса:
class ScreenSpaceEffects1 {
private FluidSimulator _fluidDynamics;
public FluidSimulator getFluidSimulator() { return _fluidDynamics; }
}
class ScreenSpaceEffects2 {
private FluidSimulator _fluidDynamics;
public void resetFluidSimulation() { _fluidDynamics.reset(); }
}
И способы вызова указанных методов:
callingMethod() {
effects1.getFluidSimulator().reset(); // Version 1
effects2.resetFluidSimulation(); // Version 2
}
На первый взгляд, версия 2 кажется немного проще и следует «правилу Деметры», скрывает реализацию Foo и т. Д. И т. Д. Но это связывает любые изменения в FluidSimulator с ScreenSpaceEffects. Например, если для сброса добавлен параметр, то имеем:
class FluidSimulator {
void reset(bool recreateRenderTargets) { /* ... */ }
}
class ScreenSpaceEffects1 {
private FluidSimulator _fluidDynamics;
public FluidSimulator getFluidSimulator() { return _fluidDynamics; }
}
class ScreenSpaceEffects2 {
private FluidSimulator _fluidDynamics;
public void resetFluidSimulation(bool recreateRenderTargets) { _fluidDynamics.reset(recreateRenderTargets); }
}
callingMethod() {
effects1.getFluidSimulator().reset(false); // Version 1
effects2.resetFluidSimulation(false); // Version 2
}
В обеих версиях callMethod необходимо изменить, но в версии 2 ScreenSpaceEffects также необходимо изменить . Может кто-нибудь объяснить преимущество наличия обертки / фасада (за исключением адаптеров, обертывания внешнего API или предоставления внутреннего).
РЕДАКТИРОВАТЬ: Один из многих реальных примеров, для которых я столкнулся с этим, а не тривиальным примером.