Nội dung
Flyweight là một mẫu thiết kế cấu trúc cho phép các chương trình hỗ trợ số lượng lớn các đối tượng bằng cách giữ mức tiêu thụ bộ nhớ của chúng ở mức thấp.
Mẫu đạt được điều đó bằng cách chia sẻ các phần trạng thái của đối tượng giữa nhiều đối tượng. Nói cách khác, Flyweight tiết kiệm RAM bằng cách lưu vào bộ nhớ đệm cùng một dữ liệu được sử dụng bởi các đối tượng khác nhau.
Cách sử dụng mẫu
Sử dụng: Mẫu Flyweight có một mục đích duy nhất: giảm thiểu lượng bộ nhớ. Nếu chương trình của bạn không gặp khó khăn với tình trạng thiếu RAM, thì bạn có thể bỏ qua mẫu này một thời gian.
Nhận dạng: Flyweight có thể được nhận dạng bằng một phương pháp tạo trả về các đối tượng được lưu trong bộ nhớ cache thay vì tạo mới.
Chương trình mẫu
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace DesignPatterns.Flyweight.Conceptual
{
// Flyweight lưu trữ một phần trạng thái chung (còn gọi là trạng thái nội tại)
// thuộc về nhiều thực thể thực. Flyweight chấp nhận phần trạng thái còn lại
// (trạng thái ngoại vi, duy nhất cho mỗi thực thể) thông qua các tham số
// phương thức của nó.
public class Flyweight
{
private Car _sharedState;
public Flyweight(Car car)
{
this._sharedState = car;
}
public void Operation(Car uniqueState)
{
string s = JsonSerializer.Serialize(this._sharedState);
string u = JsonSerializer.Serialize(uniqueState);
Console.WriteLine($"Flyweight: Displaying shared {s} and unique {u} state.");
}
}
// Flyweight Factory tạo và quản lý các đối tượng Flyweight. Nó đảm bảo rằng
// các flyweight được chia sẻ một cách chính xác. Khi client yêu cầu, factory
// sẽ trả về một phiên bản hiện có hoặc tạo một phiên bản mới, nếu nó chưa
// tồn tại.
public class FlyweightFactory
{
private List<Tuple<Flyweight, string>> flyweights = new List<Tuple<Flyweight, string>>();
public FlyweightFactory(params Car[] args)
{
foreach (var elem in args)
{
flyweights.Add(new Tuple<Flyweight, string>(new Flyweight(elem), this.getKey(elem)));
}
}
// Trả về chuỗi băm của Flyweight cho một trạng thái nhất định.
public string getKey(Car key)
{
List<string> elements = new List<string>();
elements.Add(key.Model);
elements.Add(key.Color);
elements.Add(key.Company);
if (key.Owner != null && key.Number != null)
{
elements.Add(key.Number);
elements.Add(key.Owner);
}
elements.Sort();
return string.Join("_", elements);
}
// Trả lại Flyweight hiện có với trạng thái nhất định hoặc tạo một cái mới.
public Flyweight GetFlyweight(Car sharedState)
{
string key = this.getKey(sharedState);
if (flyweights.Where(t => t.Item2 == key).Count() == 0)
{
Console.WriteLine("FlyweightFactory: Can't find a flyweight, creating new one.");
this.flyweights.Add(new Tuple<Flyweight, string>(new Flyweight(sharedState), key));
}
else
{
Console.WriteLine("FlyweightFactory: Reusing existing flyweight.");
}
return this.flyweights.Where(t => t.Item2 == key).FirstOrDefault().Item1;
}
public void listFlyweights()
{
var count = flyweights.Count;
Console.WriteLine($"\nFlyweightFactory: I have {count} flyweights:");
foreach (var flyweight in flyweights)
{
Console.WriteLine(flyweight.Item2);
}
}
}
public class Car
{
public string Owner { get; set; }
public string Number { get; set; }
public string Company { get; set; }
public string Model { get; set; }
public string Color { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Client thường tạo trước một loạt các flyweight trong giai đoạn khởi
// tạo ứng dụng.
var factory = new FlyweightFactory(
new Car { Company = "Chevrolet", Model = "Camaro2018", Color = "pink" },
new Car { Company = "Mercedes Benz", Model = "C300", Color = "black" },
new Car { Company = "Mercedes Benz", Model = "C500", Color = "red" },
new Car { Company = "BMW", Model = "M5", Color = "red" },
new Car { Company = "BMW", Model = "X6", Color = "white" }
);
factory.listFlyweights();
addCarToPoliceDatabase(factory, new Car {
Number = "CL234IR",
Owner = "James Doe",
Company = "BMW",
Model = "M5",
Color = "red"
});
addCarToPoliceDatabase(factory, new Car {
Number = "CL234IR",
Owner = "James Doe",
Company = "BMW",
Model = "X1",
Color = "red"
});
factory.listFlyweights();
}
public static void addCarToPoliceDatabase(FlyweightFactory factory, Car car)
{
Console.WriteLine("\nClient: Adding a car to database.");
var flyweight = factory.GetFlyweight(new Car {
Color = car.Color,
Model = car.Model,
Company = car.Company
});
// Client hoặc lưu trữ hoặc tính toán trạng thái ngoại vi và chuyển nó
// đến các phương thức của flyweight.
flyweight.Operation(car);
}
}
}
Kết quả
FlyweightFactory: I have 5 flyweights:
Camaro2018_Chevrolet_pink
black_C300_Mercedes Benz
C500_Mercedes Benz_red
BMW_M5_red
BMW_white_X6
Client: Adding a car to database.
FlyweightFactory: Reusing existing flyweight.
Flyweight: Displaying shared {"Owner":null,"Number":null,"Company":"BMW","Model":"M5","Color":"red"} and unique {"Owner":"James Doe","Number":"CL234IR","Company":"BMW","Model":"M5","Color":"red"} state.
Client: Adding a car to database.
FlyweightFactory: Can't find a flyweight, creating new one.
Flyweight: Displaying shared {"Owner":null,"Number":null,"Company":"BMW","Model":"X1","Color":"red"} and unique {"Owner":"James Doe","Number":"CL234IR","Company":"BMW","Model":"X1","Color":"red"} state.
FlyweightFactory: I have 6 flyweights:
Camaro2018_Chevrolet_pink
black_C300_Mercedes Benz
C500_Mercedes Benz_red
BMW_M5_red
BMW_white_X6
BMW_red_X1
Để lại một bình luận