close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

C++ Design Patterns: Flyweight

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

main.cpp

struct SharedState
{
    std::string brand_;
    std::string model_;
    std::string color_;
    SharedState(const std::string &brand, const std::string &model, const std::string &color)
        : brand_(brand), model_(model), color_(color)
    {
    }
    friend std::ostream &operator<<(std::ostream &os, const SharedState &ss)
    {
        return os << "[ " << ss.brand_ << " , " << ss.model_ << " , " << ss.color_ << " ]";
    }
};
struct UniqueState
{
    std::string owner_;
    std::string plates_;
    UniqueState(const std::string &owner, const std::string &plates)
        : owner_(owner), plates_(plates)
    {
    }
    friend std::ostream &operator<<(std::ostream &os, const UniqueState &us)
    {
        return os << "[ " << us.owner_ << " , " << us.plates_ << " ]";
    }
};
/**
 * 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ó.
 */
class Flyweight
{
private:
    SharedState *shared_state_;
public:
    Flyweight(const SharedState *shared_state) : shared_state_(new SharedState(*shared_state))
    {
    }
    Flyweight(const Flyweight &other) : shared_state_(new SharedState(*other.shared_state_))
    {
    }
    ~Flyweight()
    {
        delete shared_state_;
    }
    SharedState *shared_state() const
    {
        return shared_state_;
    }
    void Operation(const UniqueState &unique_state) const
    {
        std::cout << "Flyweight: Displaying shared (" << *shared_state_ << ") 
                                    and unique (" << unique_state << ") state.\n";
    }
};
/**
 * 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.
 */
class FlyweightFactory
{
    /**
     * @var Flyweight[]
     */
private:
    std::unordered_map<std::string, Flyweight> flyweights_;
    /**
     * Trả về chuỗi băm của Flyweight cho một trạng thái nhất định.
     */
    std::string GetKey(const SharedState &ss) const
    {
        return ss.brand_ + "_" + ss.model_ + "_" + ss.color_;
    }
public:
    FlyweightFactory(std::initializer_list<SharedState> share_states)
    {
        for (const SharedState &ss : share_states)
        {
            this->flyweights_.insert(std::make_pair<std::string, 
                                        Flyweight>(this->GetKey(ss), Flyweight(&ss)));
        }
    }
    /**
     * 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.
     */
    Flyweight GetFlyweight(const SharedState &shared_state)
    {
        std::string key = this->GetKey(shared_state);
        if (this->flyweights_.find(key) == this->flyweights_.end())
        {
            std::cout << "FlyweightFactory: Can't find a flyweight, creating new one.\n";
            this->flyweights_.insert(std::make_pair(key, Flyweight(&shared_state)));
        }
        else
        {
            std::cout << "FlyweightFactory: Reusing existing flyweight.\n";
        }
        return this->flyweights_.at(key);
    }
    void ListFlyweights() const
    {
        size_t count = this->flyweights_.size();
        std::cout << "\nFlyweightFactory: I have " << count << " flyweights:\n";
        for (std::pair<std::string, Flyweight> pair : this->flyweights_)
        {
            std::cout << pair.first << "\n";
        }
    }
};
// ...
void AddCarToPoliceDatabase(
    FlyweightFactory &ff, const std::string &plates, const std::string &owner,
    const std::string &brand, const std::string &model, const std::string &color)
{
    std::cout << "\nClient: Adding a car to database.\n";
    const Flyweight &flyweight = ff.GetFlyweight({brand, model, color});
    // 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({plates, owner});
}
/**
 * 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.
 */
int main()
{
    FlyweightFactory *factory = new FlyweightFactory({
                                    {"Chevrolet", "Camaro2018", "pink"}, 
                                    {"Mercedes Benz", "C300", "black"}, 
                                    {"Mercedes Benz", "C500", "red"}, 
                                    {"BMW", "M5", "red"}, 
                                    {"BMW", "X6", "white"}});
    factory->ListFlyweights();
    AddCarToPoliceDatabase(*factory,
                            "CL234IR",
                            "James Doe",
                            "BMW",
                            "M5",
                            "red");
    AddCarToPoliceDatabase(*factory,
                            "CL234IR",
                            "James Doe",
                            "BMW",
                            "X1",
                            "red");
    factory->ListFlyweights();
    delete factory;
    return 0;
}

Kết quả

FlyweightFactory: I have 5 flyweights:
BMW_X6_white
Mercedes Benz_C500_red
Mercedes Benz_C300_black
BMW_M5_red
Chevrolet_Camaro2018_pink
Client: Adding a car to database.
FlyweightFactory: Reusing existing flyweight.
Flyweight: Displaying shared ([ BMW , M5 , red ]) and unique ([ CL234IR , James Doe ]) state.
Client: Adding a car to database.
FlyweightFactory: Can't find a flyweight, creating new one.
Flyweight: Displaying shared ([ BMW , X1 , red ]) and unique ([ CL234IR , James Doe ]) state.
FlyweightFactory: I have 6 flyweights:
BMW_X1_red
Mercedes Benz_C300_black
BMW_X6_white
Mercedes Benz_C500_red
BMW_M5_red
Chevrolet_Camaro2018_pink

Đã đăng vào

trong

,

bởi

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *