Разрушает ли шаблон делегата инкапсуляцию?

Допустим, у меня есть класс, который принимает делегата:

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

Другие вопросы по тегам