Interested Article - Интерфейс-маркер (шаблон проектирования)

Интерфейс-маркер , маркер ( англ. marker interface pattern ) — это шаблон проектирования , применяемый в языках программирования с проверкой типов во время выполнения . Шаблон предоставляет возможность связать метаданные (интерфейс) с классом даже при отсутствии в языке явной поддержки для метаданных.

Чтобы использовать эту модель, класс реализует интерфейс («помечается интерфейсом»), а взаимодействующие с классом методы проверяют наличие интерфейса. В отличие от обычного интерфейса , который определяет функциональность (в виде объявлений методов и свойств), которой должен обладать реализуемый класс объектов, важен сам факт обладания класса маркером. Маркер лишь является признаком наличия определённого поведения у объектов класса, помеченного маркером. Разумеется, возможны и «смешанные» интерфейсы, однако при неаккуратном использовании они могут создавать путаницу.

Пример применения маркеров-интерфейсов в языке программирования Java является интерфейс . Класс должен реализовать этот интерфейс, чтобы показать, что его экземпляры могут быть записаны в . Класс ObjectOutputStream имеет публичный метод writeObject() , который содержит ряд instanceof проверок возможности записи, одной из которых является интерфейс Serializable . Если вся серия проверок оканчивается неудачей, метод выбрасывает исключение NotSerializableException .

Другим примером является интерфейс INamingContainer , который определен в .NET Framework . INamingContainer определяет элемент управления контейнером, который создает новый идентификатор пространства имен в иерархии элементов управления объекта Page . . Любой элемент управления, который реализует этот интерфейс, создает новое пространство имен, в котором обеспечивается уникальность всех идентификаторов атрибутов дочерних элементов управления в пределах всего приложения. При разработке шаблонных элементов управления необходимо реализовывать этот интерфейс, чтобы избежать конфликтов именования на странице.

Применение

Класс Repeater является элементом управления и представляет собой список с привязкой к данным, который определен в .NET Framework ( ASP.net ). Данный элемент позволяет создавать разметку путём повторения указанного шаблона для каждого элемента списка. Во избежание конфликтов имен класс помечается интерфейсом INamingContainer .

public interface INamingContainer { }
public class Control : IComponent, ...
{
    ...
    internal bool IsBindingContainer
    {
        get
        {
            return ((this is INamingContainer) && !(this is INonBindingContainer));
        }
    }
    ...
}
public class Repeater : Control, INamingContainer
{
...
}

Исходя из свойства IsBindingContainer исполняющая среда во время генерации страницы дополняет новым пространством имен идентификаторы элементов управления, находящихся в элементе управления Repeater .

Преимущества

Преимуществом использования маркера является возможность внести в языки, не поддерживающие метаданные , дополнительную информацию об особенностях поведения класса. При этом в некоторых языках, например чтобы извлечь информацию из метаданных требуется больше времени, что при частом использовании отразится на производительности. Так в языке C# , по производительности можно сравнивать конструкцию (для проверки поддержки некоторого поведения или особенностей), когда используется интерфейс-маркер:

control is INamingContainer

и конструкцию с использованием и механизма отражения :

control.GetType().IsDefined(typeof(NamingContainerAttrubute), false)

Кроме этого, некоторые языки (например, Java с использованием библиотек (англ.) , (англ.) или Similar [ источник не указан 1818 дней ] ; и другие языки [ какие? ] ) позволяют создавать или генерировать классы (и интерфейсы), помечая классы интерфейсом-маркером динамически во времени выполнения . Атрибуты или метаданные обычно связываются с классами уже во , что приводит к невозможности изменить их поведение в дальнейшем.

Недостатки

Одной из основных проблем с маркером является то, что интерфейс определяет контракт на реализацию классов, и что контракт наследуется всеми подклассами. Это означает, что вы не можете «отменить лишние реализации» маркером. В приведённом примере, если вы создаёте подкласс, и не хотите его сериализовать (возможно, потому что это зависит от частичной реализации), вы должны явно бросать исключение NotSerializableException (согласно документации ObjectOutputStream ).

Решением описанной проблемы является поддержка метаданных непосредственно в синтаксисе языка:

  • Такие языки как .NET framework и (начиная с версии Java 5 (1.5)) имеют поддержку таких метаданных. В .NET, они называются « », в Java их называют « аннотациями ». Несмотря на разные названия, они концептуально равнозначны, могут быть определены для классов, переменных, методов и параметров методов, а также быть доступны с помощью отражения .
  • В Python термин англ. marker interface применяется в компонентной архитектуре Zope (Zope Component Architecture, ZCA) и построенной на его базе системе управления содержимым . В ZCA маркерами могут отмечаться не только классы, но и отдельные объекты.

См. также

  • обобщают этот шаблон.

Примечания

  1. Bloch, Joshua. Item 37: Use marker interfaces to define types // Effective Java (Second edition) (неопр.) . — Addison-Wesley , 2008. — С. 179. — ISBN 978-0-321-35668-0 .
  2. . Дата обращения: 22 ноября 2013. 1 сентября 2013 года.

Литература

  • Joshua Bloch, "Effective Java (Second edition), " Item 37: Use marker interfaces to define types, page 179.
Источник —

Same as Интерфейс-маркер (шаблон проектирования)