Одиночка на java

Содержание:

The Singleton Pattern

Design Patterns summarizes Singleton like this:

We’ll split that at “and” and consider each half separately.

There are times when a class cannot perform correctly if there is more than one
instance of it. The common case is when the class interacts with an external
system that maintains its own global state.

Consider a class that wraps an underlying file system API. Because file
operations can take a while to complete, our class performs operations
asynchronously. This means multiple operations can be running concurrently, so
they must be coordinated with each other. If we start one call to create a file
and another one to delete that same file, our wrapper needs to be aware of both
to make sure they don’t interfere with each other.

To do this, a call into our wrapper needs to have access to every previous
operation. If users could freely create instances of our class, one instance
would have no way of knowing about operations that other instances started.
Enter the singleton. It provides a way for a class to ensure at compile time
that there is only a single instance of the class.

Several different systems in the game will use our file system wrapper: logging,
content loading, game state saving, etc. If those systems can’t create their own
instances of our file system wrapper, how can they get ahold of one?

Singleton provides a solution to this too. In addition to creating the single
instance, it also provides a globally available method to get it. This way,
anyone anywhere can get their paws on our blessed instance. All together, the
classic implementation looks like this:

class FileSystem
{
public:
  static FileSystem& instance()
  {
    // Lazy initialize.
    if (instance_ == NULL) instance_ = new FileSystem();
    return *instance_;
  }

private:
  FileSystem() {}

  static FileSystem* instance_;
};

The static member holds an instance of the class, and the private
constructor ensures that it is the only one. The public static
method grants access to the instance from anywhere in the codebase. It is also
responsible for instantiating the singleton instance lazily the first time
someone asks for it.

A modern take looks like this:

class FileSystem
{
public:
  static FileSystem& instance()
  {
    static FileSystem *instance = new FileSystem();
    return *instance;
  }

private:
  FileSystem() {}
};

C++11 mandates that the initializer for a local
static variable is only run once, even in the presence of concurrency. So,
assuming you’ve got a modern C++ compiler, this code is thread-safe where the
first example is not.

Варианты реализации

  • Ленивая инициализация: когда класс загружается во время работы приложения именно тогда, когда он нужен.

  • Простота и прозрачность кода: метрика, конечно, субъективная, но важная.

  • Потокобезопасность: корректная работа в многопоточной среде.

  • Высокая производительность в многопоточной среде: потоки блокируют друг друга минимально, либо вообще не блокируют при совместном доступе к ресурсу.

  • Не ленивая инициализация: когда класс загружается при старте приложения, независимо от того, нужен он или нет (парадокс, в мире IT лучше быть лентяем)

  • Сложность и плохая читаемость кода. Метрика также субъективная. Будем считать, что если кровь пошла из глаз, реализация так себе.

  • Отсутствие потокобезопасности. Иными словами, “потокоопасность”. Некорректная работа в многопоточной среде.

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

Вторая версия — простая защита от потоков

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

Обратите внимание, что вместо блокировки типа typeof(Singleton), как это делают в некоторых реализациях Singleton, я блокирую значение статической переменной, которая является закрытой (private) внутри класса. Блокировка объектов, к которым могут обращаться другие классы, ухудшает производительность и вносит риск взаимоблокировки

Я использую простой стиль — по возможности нужно блокировать объекты, специально созданные с целью блокировки. Обычно такие объекты должны быть использовать модификатор private.

Многопоточный Одиночка

Чтобы исправить проблему, требуется синхронизировать потоки при создании объекта-Одиночки.

main.cc: Пример структуры паттерна

/**
 * Класс Одиночка предоставляет метод `GetInstance`, который ведёт себя как
 * альтернативный конструктор и позволяет клиентам получать один и тот же
 * экземпляр класса при каждом вызове.
 */
class Singleton
{

    /**
     * Конструктор Одиночки всегда должен быть скрытым, чтобы предотвратить
     * создание объекта через оператор new.
     */
private:
    static Singleton * pinstance_;
    static std::mutex mutex_;

protected:
    Singleton(const std::string value): value_(value)
    {
    }
    ~Singleton() {}
    std::string value_;

public:
    /**
     * Одиночки не должны быть клонируемыми.
     */
    Singleton(Singleton &other) = delete;
    /**
     * Singletons should not be assignable.
     */
    void operator=(const Singleton &) = delete;
    /**
     * Это статический метод, управляющий доступом к экземпляру одиночки. При
     * первом запуске, он создаёт экземпляр одиночки и помещает его в
     * статическое поле. При последующих запусках, он возвращает клиенту объект,
     * хранящийся в статическом поле.
     */

    static Singleton *GetInstance(const std::string& value);
    /**
     * Наконец, любой одиночка должен содержать некоторую бизнес-логику, которая
     * может быть выполнена на его экземпляре.
     */
    void SomeBusinessLogic()
    {
        // ...
    }
    
    std::string value() const{
        return value_;
    } 
};

/**
 * Static methods should be defined outside the class.
 */

Singleton* Singleton::pinstance_{nullptr};
std::mutex Singleton::mutex_;

/**
 * The first time we call GetInstance we will lock the storage location
 *      and then we make sure again that the variable is null and then we
 *      set the value. RU:
 */
Singleton *Singleton::GetInstance(const std::string& value)
{
    if (pinstance_ == nullptr)
    {
        std::lock_guard<std::mutex> lock(mutex_);
        if (pinstance_ == nullptr)
        {
            pinstance_ = new Singleton(value);
        }
    }
    return pinstance_;
}

void ThreadFoo(){
    // Этот код эмулирует медленную инициализацию.
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    Singleton* singleton = Singleton::GetInstance("FOO");
    std::cout << singleton->value() << "\n";
}

void ThreadBar(){
    // Этот код эмулирует медленную инициализацию.
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    Singleton* singleton = Singleton::GetInstance("BAR");
    std::cout << singleton->value() << "\n";
}

int main()
{   
    std::cout <<"If you see the same value, then singleton was reused (yay!\n" <<
                "If you see different values, then 2 singletons were created (booo!!)\n\n" <<
                "RESULT:\n";   
    std::thread t1(ThreadFoo);
    std::thread t2(ThreadBar);
    t1.join();
    t2.join();
    
    return 0;
}

Output.txt: Результат выполнения

If you see the same value, then singleton was reused (yay!
If you see different values, then 2 singletons were created (booo!!)

RESULT:
FOO
FOO

Жизнь без секса хуже смерти

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

«Мужчины среднего возраста, снова вступившие в брак, имеют больше шансов жить половой жизнью, чем те, кто развелся, но остался один. 57 % мужчин, проживающих с партнером… заявили, что занимались сексом раз в неделю или больше… по сравнению с 43 % мужчин, проживающих без партнера. <…> Одинокие мужчины мастурбируют в два раза чаще…

Для женщин сексуальных преимуществ в браке еще больше.

54% сексом раз или более в неделю. . Ответы женщин на вопрос о том, живут ли они в целибате, рисуют картину отчаяния: 17 % вновь вышедших замуж и 77 % разведенных и незамужних женщин заявили, что ».

Дегустируем: молодой скотч «Синглтон оф Даффтаун» (десять и двенадцать лет)

Останавливают процесс проращивания зерна, по старинной шотландской традиции, дымом от тлеющего торфа. Этот аромат присутствует в десятилетнем напитке. Кроме дымка от торфа, в букете чувствуется запах фруктов и горного вереска. Вкус у скотча мягкий, чудесно сбалансированный. В нем ощущаются нотки фруктов, мёда и карамели. Этот напиток обладает янтарным цветом. Более популярным (но и более дорогим) является двенадцатилетний скотч. Именно он – тот классический напиток, вышедший в 1974 году под этикеткой Singleton of Auchroisk. Виски «Синглтон 12 лет» отзывы называют чудесно сбалансированным, элегантным, с довольно долгим послевкусием. В букете присутствуют оттенки фундука и полированного дерева, а также солодки, мха, тростникового сахара, печеных яблок и цитрусовых. Гурманы, оставившие отзывы, утверждают, что им слышится запах корочки серого хлеба. Первый глоток приносит сладость, которая затем тут же сменяется приятной кислинкой. Во вкусе угадываются нотки кофе-эспрессо, ванили, жженого сахара, черной смородины. В шлейфе царит орех.

Зачем мы его используем

Похоже у нас есть победитель. Наша обертка над файловой системой доступна всегда и везде и ее не нужно передавать с помощью каких либо ухищрений. Сам класс достаточно умен для того чтобы не позволить нам по ошибке устроить месиво из кучи его экземпляров. А вот и еще несколько приятных особенностей:

  • Экземпляр не будет создан если его никто не захочет использовать. Экономия памяти и циклов процессора — это всегда хорошо. Благодаря тому что синглтон инициализируется при первом вызове, его экземпляр не создастся если никто в игре к нему не обратится.

  • Инициализация во время выполнения. Очевидной альтернативой Синглтону является класс ос статическими переменными членами. Мне нравятся простые решения, да и использование статических классов вместо синглтона возможно. Однако у статических членов есть одно ограничение: автоматическая инициализация. Компилятор инициализирует статические переменные до вызова . Это значит, что они не могут использовать информацию, которая будет известна только после того как программа запустится и начнет работать (например, когда будет загружена файл настроек). А еще это значит, что они не могут полагаться друг на друга — компилятор не гарантирует очередности в которой относительно друг друга статические переменные будут инициализированы.

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

  • У вас может быть подкласс синглтон. Это очень мощная, но редко используемая возможность. Скажем например, что мы хотим сделать свою обертку над файловой системой кросс-платформенной. Чтобы это заработало нам нужно сделать интерфейс файловой системы абстрактным с подклассами, которые будут реализовывать интерфейсы для каждой платформы. Вот эти базовые классы.

А теперь превращаем в синглтон:

Хитрость здесь заключается в создании экземпляра:

С помощью простого переключателя компилятора мы связываем обертку файловой системы с конкретным типом. И теперь вся наша кодовая база может получать доступ к файловой системе через не привязываясь ни к какому платформозависимому коду. Вместо этого получившаяся связность инкапсулируется внутри реализации самого класса .

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

Альтернативы синглтону

Я не хочу быть тем человеком, который во всём видит плохое, но не может предложить решение проблемы. Хотя я считаю, что вы должны оценивать всю архитектуру приложения, чтобы решить, как первым делом избежать использования синглтона, я предлагаю несколько самых распространённых способов в WordPress, когда синглтон можно легко заменить механизмом, который удовлетворяет всем требованиям и лишён большинства недостатков. Но прежде чем рассказать об этом, я хочу отметить, почему все мои предложения — только компромисс.

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

  1. Инстанцирование (нужны , , ).
  2. Инстанцирование для внедрения в .
  3. Инстанцирование для внедрения в .
  4. Инстанцирование для внедрения в (нужны , ).
  5. Инстанцирование для внедрения в (нужен ).

С помощью одного вызова выстроится сверху донизу весь стек приложения с внедрением зависимостей по мере необходимости. Цели такого подхода:

  • У каждого объекта есть точный список нужных ему зависимостей, и только их он должен использовать. Когда что-либо ломается, вы можете легко изолировать ответственный за это код.
  • Тесной связи между объектами нет, все объекты при использовании внедрённых реализаций полагаются только на интерфейсы.
  • Глобального статуса нет. Каждое отдельное поддерево, стоящее выше по иерархии, будет корректно изолировано от остальных, благодаря чему разработчик не наделает багов в модуле Б, изменяя модуль А.

Однако, как бы хорошо это ни звучало, в WordPress’е так сделать невозможно, так как он не предоставляет централизованный контейнер или механизм внедрения, все плагины/темы загружаются изолированно.

Держите это в уме, пока мы будем обсуждать подходы. Идеальное решение, при котором весь стек WordPress’а инстанцируется через централизованный механизм внедрения, нам недоступно, поскольку оно требует поддержки WordPress Core. Всем описываемым далее подходам свойственны те или иные общие недостатки вроде сокрытия зависимостей посредством обращения к ним напрямую из логики вместо их внедрения.

Как правильно пить

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

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

С чем употреблять Виски «Синглтон»

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

Partial support

The following constructs are partially supported:

  • finite arithmetic sequences
  • records
  • signatures (e.g., ) in patterns
  • functional dependencies
  • type families

See the following sections for more details.

is slightly more conservative with respect to than GHC is.
The only classes that can derive without an explicit deriving
strategy are the following stock classes:

To do anything more exotic, one must explicitly indicate one’s intentions by
using the extension. fully supports the
strategy as well as the strategy (at least, for the classes
listed above). does not support the or strategies,
as there is no equivalent of at the type level.

Finite arithmetic sequences

has partial support for arithmetic sequences (which desugar to
methods from the class under the hood). Finite sequences (e.g.,
) are fully supported. However, infinite sequences (e.g., ),
which desugar to calls to or , are not supported,
as these would require using infinite lists at the type level.

Records

Record selectors are promoted to top-level functions, as there is no record
syntax at the type level. Record selectors are also singled to top-level
functions because embedding records directly into singleton data constructors
can result in surprising behavior (see
this bug report for more
details on this point). TH-generated code is not affected by this limitation
since desugars away most uses of record syntax. On the other hand,
it is not possible to write out code like
by hand.

Signatures in patterns

can promote basic pattern signatures, such as in the following
examples:

What does /not/ work are more advanced uses of pattern signatures that take
advantage of the fact that type variables in pattern signatures can alias other
types. Here are some examples of functions that one cannot promote:

  • This typechecks by virtue of the fact that aliases . However, the same
    trick does not work when is promoted to a type family, as a type family
    would consider and to be distinct type variables.

  • This typechecks by virtue of the fact that aliases . Again, this
    would not work at the type level, as a type family would consider to be
    a separate type from .

Functional dependencies

Inference dependent on functional dependencies is unpredictably bad. The
problem is that a use of an associated type family tied to a class with
fundeps doesn’t provoke the fundep to kick in. This is GHC’s problem, in
the end.

Type families

Promoting functions with types that contain type families is likely to fail due to
GHC#12564.
Note that promoting type family declarations is fine
(and often desired, since that produces defunctionalization symbols for them).

Виды виски Синглтон

В настоящее время компания-производитель решила распределить производство по трем заводам, поэтому на этикетках можно увидеть немного разнящиеся названия:

  • “Синглтон Даффтаун”.
  • “Синглтон Глен Орд”.
  • “Синглтон Глендаллан”.

Первая марка уходит на экспорт в Россию, вторая и третья – в Азию и США соответственно. Производитель заботится о том, чтобы на всех заводах соблюдались единые стандарты, и напиток всегда имел один и тот же великолепный вкус.

The Singleton of Dufftown

Коллекция, адресованная европейским потребителям, была создана в честь королевы Виктории.

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

Односолодовые напитки линейки обладают гладкостью, округлостью, чистотой и исключительной ароматностью. Характерные тона: ваниль, фрукты, ягоды, мед, оттенки дуба.

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

Скотчи хороши в чистом виде, в сочетании с популярными закусками и в составе коктейлей.

12 Years Old

Выдержанный 12 лет виски обладает богатым янтарным цветом с намеком на красное полированное дерево. Знакомство начинается с аромата ореха и древесины, после раскрываются ноты печеных яблок, коричневого сахара.

Мягкий, натуральный и богатый шотландский односолодовый виски 12-летней выдержки со сладкими фруктовыми нотами, который дарит приятную теплоту. Его цвет – богатый, янтарный, с отблесками полированного красного дерева. Аромат открывается древесными и ореховыми нотами, затем появляется запах печеных яблок, коричневого сахара.

Вкус напитка сладкий, с отчетливым привкусом ореха, фруктов и кофе. Послевкусие, которое оставляет The Singleton of Dufftown 12 Years Old неповторимо. Оно длится долго, соединяя сладость и ореховый оттенки.

15 Years Old

15 летний виски отличает его от других представителей превосходством в балансе аромата и вкуса. Аромат скотча отличается пряными оттенками карамельно-медовых теплых и яблочных нот.

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

18 Years Old

Прекрасно сбалансированный, мягкий и богатый виски с 18-летней выдержкой, отличающийся вкусом осенних фруктов, оттененных ореховыми нотами. Цвет напитка глубокий, янтарный, а аромат – мягкий, осенний, с оттенком сладких фруктов, яблок и ягод.

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

The Singleton of Glen Ord

Линейка, созданная на самой старой из винокурен Синглтона, относится к продукции шотландского Высокогорья. В этих напитках нет нежности Спейсайда и дымности Айлы, но есть собственная мощь и элегантность.

Виски Черного Острова обладают живым характером, удивляют тонами темных ягод: вишни и черной смородины.

Сбалансированные, сложные букеты рождаются в результате длительной ферментации и медленной дистилляции.

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

Tailfire

Виски Тэйлфайр вискокурни Даффтаун выдержано в бочках из европейского дуба. Это помогло к классическим фруктовым нотам добавить красные ягоды и сладкую ваниль. Аромат этого напитка завораживает с первого момента: сладкий банан сменяется терпкостью апельсиновой цедры, полностью раскрывается нотами спелых груш и красных яблок, а также клубничной и земляничной сладостью.

Открывается вкус выраженными нотами зерна и переходит в насыщенность сладкого ягодного сиропа или варенья. Послевкусие освежает тонкими нотами шоколада, кокоса и изысканного дыма.

The Singleton Of Glendullan

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

Европейская древесина сообщает им сбалансированность, гладкость и элегантную сухость специй.

Характерные тона: мед, ваниль, яблоко, груша, клубника, изюм, пряности.

Sunray

Виски Санрей насыщен теплыми медовыми нотами и отличающейся балансом легкой текстуры и полноценности вкуса. В аромате чувствуется сочетание фруктов, шоколада и ванили.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *