Хтось має конкретний приклад використання моделі Flyweight Pattern? [зачинено]


21

Я вивчав дизайнерські зразки і натрапляв на схему масової ваги. Я намагаюся побачити можливості використовувати шаблон у своїх програмах, але у мене виникають проблеми, коли його використовувати. Крім того, які ознаки застосовують схему ваги мухи, коли я читаю код інших народів?

Відповідно до визначення, воно говорить:

Використовуйте спільний доступ для ефективної підтримки великої кількості дрібнозернистих об'єктів.

Якщо я читаю це правильно Словники та хешшлети можуть бути екземплярами літальних ваг, це правильно?

Заздалегідь спасибі.


7
Лише невеликий анекдот про махові ваги: ​​мені колись довелося створювати великі файли Excel (до 500k записів, понад 100 стовпців) за допомогою стороннього API. Стилі для комірок стали надзвичайно об'ємними. Отож, коли потрібен стиль, перевіряється хештеб, якщо рівний стиль вже існує, а потім надається лише посилання на цей стиль. Ця модифікація зробила можливим цей експорт. Тепер, маючи настільки багато даних у відмінність, на мою думку, це безумство. Але контролери мали свої макроси аналізу, які вони хотіли зберегти.
Сокіл

9
Коментар: Я сподіваюся, що люди, які пишуть зразки та книги OO, і статті, потрапляють у реальний світ середнього програміста і перестають користуватися англійською мовою юристів!
NoChance

1
"Мені колись довелося створити великі файли Excel (до 500k записів, понад 100 стовпців)" - це не так багато порівняно з тим, що здатні створити деякі трейдери ;-)
quant_dev

Прочитавши декілька цих прикладів, я думаю, що стиснення даних в пам'яті було б чудовим місцем для впровадження цієї методики. Дякую за допомогу!
Джеремі Е

Клітини таблиці в GWT - це маховики.
user16764

Відповіді:


19

Один із прикладів - у бібліотеках Java. У Java є примітивні типи (наприклад int, це 32-бітове ціле число) та обгортки для них (наприклад Integer, які обгортання int). Існують методи "поле" intв Integerі розпакувати Integerв int. Обгортки необхідні, тому що примітивні типи не є об'єктами і, отже, не можуть, наприклад, використовуватися як ключі в Maps або розміщуватися в Collections.

Метод боксу використовує масив полегшених предметів як своєрідний кеш для Integers, що відповідає intзначенню від -128 до 127. Оскільки ці значення, найімовірніше, будуть використовуватися як ключі або розміщені в колекціях, це зменшує розподіл та використання пам'яті. (Якщо 5000000 Integers представляє значення 0, яке плаває навколо, це використовує 5000000 разів більше пам'яті, ніж повторне використання полегшеного екземпляра).



1
Тож інтерновий пул для рядків у C # - це ще один приклад правильної схеми?
Джеремі Е

1
@Jeremy E: Так, на мою думку, ви можете назвати рядок інтернування програми з легкої ваги, хоча і для рядків, мова йде не лише про споживання пам'яті, але і про ефективність виконання.
Сокіл

Вказівники з міткою Objective-C доводять це до крайності. Укладені цілі числа до 56 біт і багато рядків до шести символів навіть не виділяються як об'єкти, але вся інформація упаковується в сам покажчик об'єкта.
gnasher729

9

Графіка. Як правило, растрові зображення (які є основою більшості комп'ютерної графіки на рівні споживачів) є дешевим процесором, але з ним дорого пам'яті (що нормально, оскільки пам'ять дешева, але процесор дорогий). Якщо це растрове зображення має повторюватися багато разів під час надання більшого інтерфейсу (від значків у додатку GUI для Windows, до символів шрифту в текстовому процесорі, до текстур на поверхнях у 3D-грі), це має багато сенсу завантажте зображення в пам'ять один раз і просто вкажіть на нього за допомогою дуже простих об'єктів, які дешево зробити, а самі не займають багато пам'яті. Спрайт, який є просто точкою у графічному просторі, на якій має відображатися зображення, - це лише 3D-точка та вказівка ​​пам’яті на перший піксель зображення, який потрібно використовувати. МОЖЕ, він також включає розміри частини файлу образу спрайту, який буде використовуватися, або в графічному, або в пам'яті. Цю інформацію можна дуже недорого змінити, скажімо, змінити зображення або розташування спрайту, і це можна зробити без завантаження нового зображення щоразу, тим самим різко підвищивши продуктивність базової програми для маніпулювання та відображення належних частин належних зображень для відображення повноцінної "сцени" інтерфейсу.


3

CharacterЕкземпляри діапазону ASCII в Smalltalk - це махові ваги.

Коли ви оцінюєте щось на кшталт Character space, Character class >> #value:виконайте:

value: anInteger 
    "Answer the Character whose value is anInteger."

    anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
    ^ CharacterTable at: anInteger + 1.

Змінна класу CharacterTableініціалізується так:

initialize
    "Create the table of unique Characters, and DigitsValues."
    "Character initializeClassificationTable"

    CharacterTable ifNil: [
        "Initialize only once to ensure that byte characters are unique"
        CharacterTable := Array new: 256.
        1 to: 256 do: [:i | CharacterTable
            at: i
            put: (self basicNew setValue: i - 1)]].
    self initializeDigitValues

Отже, коли ви створюєте String, діапазон ASCII Characterбуде виходити з того, CharacterTableа не бути щойно створеним.


3

Метою використання легкої ваги є уникнути непотрібної ініціалізації об'єкта і, таким чином, заощадити місце. Як визначено GOF , об'єкт може мати два стани, внутрішній та зовнішній стан:

  • Внутрішній стан: зберігається у легкій вазі; вона складається з інформації, незалежної від контексту махових ваг, що робить її зручною.
  • Зовнішній стан: залежить від та змінюється залежно від контексту легкої ваги, тому не можна ділитися. Клієнтські об'єкти відповідають за передачу зовнішнього стану легкої ваги, коли вона цього потребує.

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

Дилема тут полягає в тому, як створити клас персонажів. Клас char c"Характер" повинен бути основним (внутрішнім станом) об'єктом. Однак символ може мати шрифт і і розмір (зовнішній стан); таким чином нам потрібно зберігати його зовнішній стан на рядку (клієнта) та звертатися до нього за потреби. Для цього створено два списки, в яких зберігаються шрифти та розміри.

Дотримуючись схему Flyweight, символу тепер можна використовувати багаторазово, а на об'єкти посилаються з певного списку об'єктів (пуловий пул), який містить усі символи ( Characterоб'єкти) ASCII .

Ось що я описав візуально:

введіть тут опис зображення

Для друку «привіт» Characterпотрібні лише 4 об’єкти замість 5. Після зміни шрифту нові об’єкти не потрібні; зауважте, що це було б неможливо, якби ми зберігали зовнішній стан у класі символів, наприклад,

class Character
{
    char c;
    int Size;
    Font font;

    ....
}

Застосування цього шаблону на великих наборах даних призведе до значних оптимізацій щодо складності пам'яті програми та повторного використання об'єктів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.