0

Допустим, у меня есть класс, который принимает делегат:Разбивает ли шаблон делегирования делегат?

public class DelegateContainer 
{ 
    private IDelegate delegate; 

    public DelegateContainer(IDelegate delegate) 
    { 
     this.delegate = delegate; 
    } 

    public void doSomething() 
    { 
     delegate.doSomethingOnlyForThisPurpose(); 
    } 
{ 

Как вы можете видеть, метод делегата doSomethingOnlyForThisPurpose() существует только называться классом делегирующей. Однако требуется, чтобы этот метод был общедоступным и мог быть выполнен любым. Если это абсолютно не должно выполняться ничем иным, кроме делегирующего класса, к которому он присоединен (особенно если делегирующий класс проходит в зависимости), разве это не разрушает инкапсуляцию? Единственный способ, которым я решил обойти это, - это усовершенствовать объект, который может быть создан только делегирующим классом (внутренним классом), который передается каждому вызванному методу. Тем не менее, это очень запутанно и не является водонепроницаемым. Есть ли какой-либо путь вокруг этого или это патологический?

Примечание: Я хочу придерживаться этого композиционного подхода, поэтому я бы предпочел не прибегать к наследованию.

ответ

0

Не следует прерывать инкапсуляцию. Ваша реализация 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), если вы «застенчивы» опубликовать его (это плохая новость). Это проблема дизайна, но не патология шаблона делегирования.