Java: функциональные объекты как стратегии - PullRequest
3 голосов
/ 03 ноября 2011

Я читаю Эффективную Java. В разделе, где говорится об использовании функциональных объектов в качестве стратегий, представлен следующий абзац.

Поскольку интерфейс стратегии служит типом для всей его конкретной стратегии экземпляры, конкретный класс стратегии не должен быть обнародован для экспорта конкретного стратегия. Вместо этого «хост-класс» может экспортировать открытое статическое поле (или статическую фабрику). метод), тип которого является интерфейсом стратегии, а конкретный класс стратегии может быть частным вложенным классом хоста

   // Exporting a concrete strategy
  class Host {
        private static class StrLenCmp
               implements Comparator<String>, Serializable {

        public int compare(String s1, String s2) {
            return s1.length() - s2.length();
        }
    }

    // Returned comparator is serializable
    public static final Comparator<String>
    STRING_LENGTH_COMPARATOR = new StrLenCmp();
    ... // Bulk of class omitted
  }        

Мой вопрос: Есть ли какое-то конкретное преимущество использования вышеуказанного способа? В чем проблема экспорта стратегии путем обнародования конкретной стратегии?

Ответы [ 3 ]

2 голосов
/ 03 ноября 2011

Это та же проблема, что и сделать что-нибудь открытым - инкапсуляция.

Самая узкая область действия для объекта значительно упрощает рассуждения о том, как этот объект используется, и может значительно облегчить обслуживание (вы знаете, что private объект может использоваться только в том же исходном файле, на который вы просматриваете , но вы никогда не узнаете, сколько людей используют объект public и каким образом).

Каждая Java-программа будет работать, если вы объявите все как общедоступные. Но это немного похоже на ящик Пандоры - как только вы открыли доступ к чему-либо, его трудно вернуть назад.

Не публикуя конкретную стратегию, вы не позволяете другим классам / приложениям использовать ее в своих целях, что означает, что вам не нужно беспокоиться о том, чтобы создать ее как полноценную, блестящую, стабильную, общедоступную. класс с четко определенным интерфейсом. Вы можете просто написать, что работает для вас прямо сейчас, и знать, что у вас есть свобода изменить его так, как вы захотите позже.

2 голосов
/ 03 ноября 2011
  • Публичный материал - это ваш API. Если вы отправляете свой код, а затем вам необходимо изменить реализацию стратегии, вы фактически нарушили свой API для всех, кому вы отправили код.

  • Таким образом, пока не требуется иное, все должно быть в самом узком объеме.

  • Мы также поместили его в статический вложенный класс, потому что мы не используем эту стратегию в другом месте.

2 голосов
/ 03 ноября 2011

Да, есть.Таким образом, вы возвращаете интерфейс, а не конкретный класс, поэтому, если вы изменяете конкретную реализацию интерфейса Comparator, вам также не нужно изменять клиентские классы (я думаю, что это самая важная причина использования интерфейсов).

Например:

//inside aClass

Comparator c = Host.STRING_LENGTH_COMPARATOR; //Programming against interfaces is different from:
StrLenCmp  c = Host.STRING_LENGTH_COMPARATOR; //programming against concrete class

Предположим, что в будущем вы измените StrLenCmp с другой реализацией (назовем это NewStrLenCmp), чем если вы программировали для интерфейса Comparator, вам не нужно изменять aClass.

Comparator c = Host.STRING_LENGTH_COMPARATOR; //still work because interface doesn't changed
NewStrLenCmp  c = Host.STRING_LENGTH_COMPARATOR; // problem: you need to modify the client class in order to use the new concrete type: bad idea
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...