Как можно использовать шаблон прокси для замены синглтона? - PullRequest
9 голосов
/ 19 января 2010

Это ответ на некоторые комментарии в что плохого в синглетах

Там было предложено использовать прокси-шаблон вместо одиночного для кэширования данных БД. Но я не вижу преимущества, и на самом деле синглтон кажется более «управляемым».

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

(PS: если вы собираетесь сказать «потому что это более« проверяемое »!» - уточните, я все еще привыкаю к ​​этим концепциям)

Спасибо за вашу помощь!

Ответы [ 3 ]

8 голосов
/ 02 февраля 2010

отказ от ответственности: я говорю здесь на языке java

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

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

проблема в том, что когда вы начинаете иметь синглтон, вам нужно знать каждую мельчайшую деталь того, что вы делаете, потому что вы делаете много строгих предположений о вашем синглтон-классе, самое важное, что это будет единственный класс в системе. затем вы начинаете использовать его, предполагая, что он всегда будет единственной точкой входа в ваш ресурс, и тогда возникает неприятная ошибка, поскольку ваш класс теперь развернут на сервере ejb, и у каждого контекста ejb есть свой собственный синглтон, плюс еще один синглтон для каждый jsp, который был перезагружен с сервера, плюс один синглтон за каждый сериализацию и десериализацию вашего синглтона (как вы, вероятно, забыли переопределить метод readResolve ()).

так вот почему синглтон нужно использовать с большой осторожностью, и теперь он считается антипаттерном, несмотря на то, что он полностью полезен по назначению.

в случае кеша базы данных, было бы лучше, чтобы каждый класс, нуждающийся в кеше, использовал прокси для этого ресурса «кеша», поэтому вы можете добавить логику для «поиска ресурса» внутри Сам прокси вместо того, чтобы логика была привязана к извлечению одиночного кэша, который может работать или не работать в зависимости от среды.

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

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

прокси предназначены для выполнения роли «предоставления ресурса в системе», будь то отдельное приложение, система клиент-сервер, различные компоненты одной и той же системы и т. Д., С дополнительным преимуществом, что при использовании метода èrpxy поиска ресурса непрозрачен. у вас может быть, что они предоставляют вам синглтон, содержащий хэш-карту кэшированных значений, у вас может быть доступ к memcached где-то в сети, вы можете иметь их для чтения csv во время тестов, и все это без изменения способа их вызова из приложения.

2 голосов
/ 30 января 2010

На мой взгляд, здесь нет ни «ни, ни». Класс может реализовывать несколько шаблонов проектирования одновременно. Я бы сказал, что класс, реализующий доступ к внешней базе данных, в любом случае является прокси (в данном случае удаленным прокси). Если вы считаете кеширование дополнительной функциональностью, это также декоратор.

Итак, настоящий вопрос в том, должен ли это быть также синглтон? Предположим, что существует только одна внешняя база данных. Должен ли быть только один CachingDBProxy? Я бы сказал, это зависит от использования:

Если есть несколько клиентов, имеющих доступ к аналогичным данным, они могут получить выгоду, если они используют один и тот же CachingDBProxy. Данные, необходимые одному клиенту, возможно, уже были нужны другому клиенту, поэтому их можно извлечь из кэша вместо необходимости дорогостоящего доступа к базе данных.

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

Итак, сколько CachingDBProxies должно быть, зависит от использования. CachingDBProxy не должен ограничивать его использование без уважительной причины, поэтому он не должен обеспечивать наличие только одного экземпляра, поэтому в этом случае CachingDBProxies не должен быть Singleton, ИМХО. Только клиенты могут знать, сколько CachingDBProxies им подходит.

С другой стороны, если у нас есть прокси-сервер для конкретного ресурса, который может обрабатывать только один доступ за раз, это может быть Singleton. Но это отличный случай от вышеупомянутого случая. Здесь требование исходит непосредственно из области, за которую отвечает Прокси (его цель - направить доступ к этому конкретному ресурсу).

0 голосов
/ 19 января 2010

Я могу только представить, что шаблон прокси используется для прокси между кэшированными данными и загрузкой данных (иначе говоря, ленивая загрузка).

Сортировка:

class DbProxy
{
  private static Data cache = null; // Sort-of Singleton

  public static Data GetData(String query)
  {
    if (DbProxy.cache == null)
    {
      // Data = Do Stuff to read Data
      DbProxy.cache = Data;
    }
    return DbProxy.cache;
  }
}

Это имеетПреимущество в том, что код, использующий это, не должен заботиться о том, существуют ли уже данные, он просто должен вызвать GetData и завершить./

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...