当前位置:网站首页>Enjoy element mode (flyweight)

Enjoy element mode (flyweight)

2022-06-26 13:06:00 baboon_ chen

Reference resources :

Xiangyuan design mode (refactoringguru.cn)

The flyweight pattern ( Detailed Edition ) (biancheng.net)

One 、 What is the sharing mode ?

Definition : By sharing the same state shared by multiple objects , Allows you to load more objects in a limited amount of memory .

You need to split the data members of the class into two parts : Internal state 、 External state . The inside is fixed , External is adjustable data . For unchanging intrinsic information , Can be stored in a shared way , This reduces memory usage .

such as , Black and white pieces in go and Gobang , The position of the pieces on the chessboard changes , Color is fixable . So only two pieces need to be stored : The spots 、 An albino . The impact point can be stored in a two-dimensional matrix . Registration of vehicle information in traffic police system , Vehicle information can be divided into internal states ( brand 、 model 、 Color )、 External state ( Belong to 、 License plate ).


 Insert picture description here

Two 、 Example

Enjoying yuan (Flyweight) The pattern includes the following main characters :

  1. Abstract enjoyment (Flyweight): It is the base class of all the concrete primitive classes , The public interface that needs to be implemented for the specific membership specification , The external state of the non sharer is passed in as a parameter through the method .
  2. Enjoy the specific yuan (Concrete Flyweight): Implement the interface specified in the abstract membership role .
  3. Non enjoyment yuan (Unsharable Flyweight) : It's an external state that can't be shared , It is injected into the relevant methods of the specific sharer in the form of parameters .
  4. The flyweight factory (Flyweight Factory): Responsible for creating and managing the shareware roles . When a client object requests a sharing object , Check whether there are qualified sharing objects in the system , If it exists, provide it to the customer ; If it doesn't exist , Create a new share object .
  5. The customer's role is to obtain the specific enjoy yuan through enjoy yuan factory , And visit the specific methods of sharing .


 Insert picture description here

1、 Vehicle management system ( Vehicle information registration )

/**
 * Flyweight Design Pattern
 *
 *  By sharing common parts of state among multiple objects , Instead of saving all the data in each object , Allows you to put more objects into the available RAM in .
 *  The example shows a police car management system , The shared information of each car is ( brand 、 model 、 Color ), Unshared information includes ( Belong to 、 License plate ).
 */

#include <iostream>
#include <string>
#include <unordered_map>

//  Sharing status ( Internal state )
struct SharedState
{
    std::string brand_;  //  brand 
    std::string model_;  //  model 
    std::string color_;  //  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_ << " ]";
    }
};

//  Unshared state ( External state )
struct UniqueState
{
    std::string owner_;  //  Belong to 
    std::string plates_; //  License plate 

    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_ << " ]";
    }
};

/**
 *  Enjoying yuan (Flyweight) Class contains the state shared in the original object . 
 *  The same meta object can be used in many different scenarios .
 *  The state stored in the element is called “ Internal state ”. The state passed to a method of enjoyment is called “ External state ”.
 */
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";
    }
};

/**
 *  The flyweight factory (Flyweight Factory) It will manage the existing cache pool .
 *  With the factory , The client does not need to create the share element directly , They simply call the factory and pass it some internal state of the target share .
 *  The factory will look up the previously created shares according to the parameters , If you find a share that meets the criteria, it is returned , If it is not found, create a new share according to the parameters .
 */
class FlyweightFactory
{
private:
    //  disorder map Containers do not need to be sorted ,hash lookup .
    std::unordered_map<std::string, Flyweight> flyweights_;
    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)));
        }
    }

    //  If you don't have one, you can create one , If you have, you can reuse the existing shared elements 
    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);
    }
    
    //  Print meta cache 
    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";
        }
    }
};

//  client , By transmission key Get Xiangyuan from Xiangyuan factory .
//  Record the vehicle information to the public security vehicle management database 
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});
    flyweight.Operation({owner, plates});
}

int main()
{
    //  The client code usually creates a bunch of pre populated during the initialization phase of the application flyweights.
    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;
}

3、 ... and 、 Advantages and disadvantages , Applicable scenario

advantage

  • If there are many similar objects in the program , Then you can save a lot of memory .

shortcoming

  • You may need to sacrifice execution speed in exchange for memory , Because others need to recalculate part of the scenario data every time they call the share element method .
  • To make objects shareable , You need to externalize some states that you can't share , This will increase the complexity of the program .

原网站

版权声明
本文为[baboon_ chen]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206261224551981.html