1. Что такое шаблон "Приспособленец" (Flyweight)
1.1 Определение и концепция
Шаблон "Приспособленец" (Flyweight) - это структурный шаблон проектирования, целью которого является минимизация количества общих объектов, что позволяет экономить память и улучшать производительность. Шаблон "Приспособленец" (Flyweight) уменьшает создание и использование объектов, разделяя одинаковые или похожие объекты и достигая оптимизации производительности.
1.2 Отличие от других шаблонов проектирования
По сравнению с другими шаблонами проектирования, шаблон "Приспособленец" (Flyweight) в основном сосредоточен на общем использовании объектов. Он разделяет объекты на общие внутренние состояния и неподдерживаемые внешние состояния. За счет общих внутренних состояний он уменьшает создание и расход памяти объектов, повышая эффективность системы.
2. Характеристики и преимущества шаблона "Приспособленец" (Flyweight)
Основные характеристики и преимущества шаблона "Приспособленец" (Flyweight) включают:
- Минимизированное использование памяти: Это уменьшает расход памяти за счет общего использования одинаковых или похожих объектов.
- Улучшенная производительность: Это уменьшает создание и уничтожение объектов, ускоряя работу системы.
- Поддержка большого количества мелких объектов: Он может создавать большое количество мелких объектов, не занимая слишком много места в памяти.
- Упрощенная структура системы: Путем разделения внутренних и внешних состояний объектов он упрощает структуру и сложность системы.
3. Примеры практического применения шаблона "Приспособленец" (Flyweight)
Шаблон "Приспособленец" (Flyweight) может найти применение в следующих сценариях:
- Игровые объекты частиц: Свойства каждого объекта частиц могут быть разделены на внутренние и внешние состояния, а объекты частиц с одинаковыми свойствами могут быть общими.
- Объекты подключения в сетевых серверах: Свойства объектов подключения могут быть разделены на внутренние и внешние состояния, и существующие объекты подключения могут быть повторно использованы перед их утилизацией.
4. Реализация шаблона "Приспособленец" (Flyweight) на Golang
4.1 UML-диаграмма классов
UML-диаграмма классов шаблона "Приспособленец" (Flyweight) на Golang выглядит следующим образом:
 на Golang")
4.2 Введение в пример
В этом примере мы создадим графический редактор на основе шаблона "Приспособленец" (Flyweight), содержащий круги разного цвета, и уменьшим использование памяти за счет общего использования объектов кругов одинакового цвета.
4.3 Шаги реализации
4.3.1 Создание интерфейса "Приспособленец" (Flyweight) и класса конкретного приспособленца (Concrete Flyweight)
Сначала нам нужно создать интерфейс "Приспособленец" (Flyweight) для определения операций общих объектов. Затем мы можем создать класс "ConcreteFlyweight" для реализации интерфейса "Приспособленец" (Flyweight) и включения внутренних состояний.
// Flyweight определяет интерфейс объектов приспособленца
type Flyweight interface {
Operation(extrinsicState string)
}
// ConcreteFlyweight представляет конкретный объект приспособленца, реализующий интерфейс Flyweight
type ConcreteFlyweight struct {
intrinsicState string
}
// Operation реализует метод операции общего объекта
func (f *ConcreteFlyweight) Operation(extrinsicState string) {
fmt.Printf("Конкретный объект приспособленца, внутреннее состояние: %s, внешнее состояние: %s\n", f.intrinsicState, extrinsicState)
}
4.3.2 Создание класса FlyweightFactory
Затем мы можем создать класс "FlyweightFactory" для управления и общего использования объектов приспособленца. Этот класс фабрики поддерживает словарь "flyweights" для хранения созданных объектов приспособленцев.
// Класс FlyweightFactory
type FlyweightFactory struct {
flyweights map[string]Flyweight
}
// GetFlyweight извлекает или создает объект приспособленца из фабрики
func (f *FlyweightFactory) GetFlyweight(key string) Flyweight {
if fw, ok := f.flyweights[key]; ok {
return fw
}
flyweight := &ConcreteFlyweight{
intrinsicState: key,
}
f.flyweights[key] = flyweight
return flyweight
}
4.3.3 Пример вызова клиента
Наконец, мы можем создать класс "Client" для демонстрации использования шаблона "Приспособленец" (Flyweight) для реализации графического редактора.
// Класс Client
type Client struct {
flyweight Flyweight
}
// Операция выполняет операцию
func (c *Client) Operation() {
c.flyweight.Operation("внешнее состояние")
}
4.4 Предпосылки реализации и лучшие практики
4.4.1 Обмен состоянием и безопасность потоков
При использовании шаблона "легковес" следует уделять внимание обмену внутренним состоянием и безопасности потоков. Поскольку объекты "легковес" используются несколькими клиентами, необходимо обеспечить согласованность внутреннего состояния.
4.4.2 Управление пулом объектов
Для лучшего управления и повторного использования объектов "легковес" можно использовать пул объектов для хранения созданных объектов "легковес". Пул объектов может увеличить уровень повторного использования объектов и уменьшить накладные расходы на создание и уничтожение объектов.
4.4.3 Внешнее управление состоянием объекта
Шаблон "легковес" отделяет внутреннее состояние и внешнее состояние объектов, но внешнее состояние должно управляться клиентом. При использовании объектов "легковес" клиент должен передавать внешнее состояние объекту "легковес" для выполнения операций.
Полный пример кода
Ниже приведен полный пример кода на Golang:
package main
import "fmt"
// Flyweight определяет интерфейс объекта "легковес"
type Flyweight interface {
Operation(extrinsicState string)
}
// ConcreteFlyweight представляет конкретный объект "легковес" и реализует интерфейс Flyweight
type ConcreteFlyweight struct {
intrinsicState string
}
// Operation реализует метод операции для общих объектов
func (f *ConcreteFlyweight) Operation(extrinsicState string) {
fmt.Printf("Конкретный объект 'легковес', внутреннее состояние: %s, внешнее состояние: %s\n", f.intrinsicState, extrinsicState)
}
// Класс FlyweightFactory
type FlyweightFactory struct {
flyweights map[string]Flyweight
}
// GetFlyweight извлекает или создает объект "легковес" из фабрики
func (f *FlyweightFactory) GetFlyweight(key string) Flyweight {
if fw, ok := f.flyweights[key]; ok {
return fw
}
flyweight := &ConcreteFlyweight{
intrinsicState: key,
}
f.flyweights[key] = flyweight
return flyweight
}
// Класс Client
type Client struct {
flyweight Flyweight
}
// Operation выполняет операцию
func (c *Client) Operation() {
c.flyweight.Operation("внешнее состояние")
}
func main() {
factory := &FlyweightFactory{
flyweights: make(map[string]Flyweight),
}
flyweight1 := factory.GetFlyweight("A")
flyweight1.Operation("внешнее состояние 1")
flyweight2 := factory.GetFlyweight("B")
flyweight2.Operation("внешнее состояние 2")
client := &Client{
flyweight: factory.GetFlyweight("A"),
}
client.Operation()
}