Разрушает ли шаблон делегата инкапсуляцию?
Допустим, у меня есть класс, который принимает делегата:
public class DelegateContainer
{
private IDelegate delegate;
public DelegateContainer(IDelegate delegate)
{
this.delegate = delegate;
}
public void doSomething()
{
delegate.doSomethingOnlyForThisPurpose();
}
{
Как вы можете видеть, метод doSomethingOnlyForThisPurpose() делегата существует только для вызова делегирующим классом. Однако требуется, чтобы этот метод был общедоступным и мог выполняться любым способом. Если он абсолютно не должен выполняться чем-либо, кроме делегирующего класса, к которому он присоединен (особенно, если делегирующий класс переходит в зависимость), не нарушает ли это инкапсуляцию? Единственный способ обойти это - создать объект, который может быть создан только делегирующим классом (внутренним классом), который передается каждому вызываемому методу. Тем не менее, это очень запутанный и не водонепроницаемый в любом случае. Есть ли способ обойти это или это патология?
Примечание: я хочу придерживаться этого композиционного подхода, поэтому я бы не стал прибегать к наследованию.
1 ответ
Это не должно нарушать инкапсуляцию. Ваша реализация IDelegate публикует некоторое поведение, которое может вызывать любой, у кого есть ссылка на экземпляр этого, так что оно должно быть реализовано с необходимой абстракцией, как и любое другое публичное поведение. Если вы хотите, чтобы кто-то имел экземпляр, вы обнародуете свой конструктор. Если вы этого не сделаете, то вы делаете так, как сделали (используя приватный или защищенный конструктор).
Цель вашего IDelegate.doSomethingOnlyForThisPurpose
реализация должна заключаться в том, чтобы делать то, что она делает, независимо от того, DelegateContainer
, Я имею в виду, что если этот метод опасен, если его используют "чужие руки", то он тесно связан с DelegateContainer
, В этом случае это был не шаблон делегирования, который нарушил инкапсуляцию.
Просто быстрое примечание:
Я не знаю, какой язык вы используете. В C#
Вы можете реализовать IDelegate.doSomethingOnlyForThisPurpose
явно для использования теми, кто особенно заинтересован в этом интерфейсе:
class MyClass: IDelegate
{
void IDelegate.doSomethingOnlyForThisPurpose() {
// This method is only visible by
// who is representing your object as IDelegate.
// It's not visible by who is representing it as MyClass.
}
}
Вывод: у вас не должно быть не частного метода, называемого doSomethingOnlyForThisPurpose
если "OnlyForThisPurpose" означает, что вызывать его в любое время небезопасно (вы уже это знаете), и вам не нужно, чтобы ваш метод вызывался вне вашего класса (посредством DelegateContainer
) если вы "стесняетесь" его опубликовать (это плохие новости). Это проблема дизайна, но не патология паттернов делегирования.