// Adaptee interface that needs to be adapted to the Target interface classBaseMediaPlayer { public: virtualvoidplayMp4(std::string filename)= 0; virtualvoidplayAvi(std::string filename)= 0; };
// Concrete implementation of the Adaptee interface classMp4Player : public BaseMediaPlayer { public: voidplayMp4(std::string filename)override{ std::cout << "Playing MP4 file: " << filename << std::endl; } voidplayAvi(std::string filename)override{ // Do nothing } };
// Target interface that the client code expects to use classClientMediaPlayer { public: virtualvoidplay(std::string filename)= 0; };
// Adapter that adapts the Adaptee interface to the Target interface classMediaAdapter : public ClientMediaPlayer { public: MediaAdapter(BaseMediaPlayer* player) : player_(player) {} voidplay(std::string filename)override{ if (filename.find(".mp4") != std::string::npos) { player_->playMp4(filename); } elseif (filename.find(".avi") != std::string::npos) { player_->playAvi(filename); } else { std::cout << "Unsupported file format" << std::endl; } } private: BaseMediaPlayer* player_; };
// Concrete implementation of the Target interface that uses the Adapter classAudioPlayer : public ClientMediaPlayer { public: voidplay(std::string filename)override{ // Check if the file format is supported if (filename.find(".mp3") != std::string::npos) { std::cout << "Playing MP3 file: " << filename << std::endl; } elseif (filename.find(".vlc") != std::string::npos || filename.find(".mp4") != std::string::npos) { // Use the MediaAdapter to play VLC and MP4 files MediaAdapter adapter(newMp4Player()); adapter.play(filename); } else { std::cout << "Unsupported file format" << std::endl; } } };
Bridge Pattern
Separate abstraction and implementation. Decouple classes.
classVectorRenderer: public Render { public: virtualvoidrenderCircle()override{
} };
// class Shape is abstraction, while the Renderer obj is implementation. Use a reference so that the real implementation of Renderer could change. classShape { protected: // can be also pointer, but use reference to avoid null pointer issue Renderer& renderer; public: Shape(Renderer& renderer): renderer(renderer) {
} virtualvoiddraw()= 0; }
classCircle: public Shape { public: Circle(Renderer& renderer): Shape(renderer) {
Instead of using nullptr in some cases, use a special class which represents the nullptr, i.e. has the same interfaces but perform nothing.
Strategy Pattern
Dynamically change the behavior of an object at runtime by providing multiple strategies to choose from.
Comparing with state pattern which is used to change an object’s behavior based on its internal state, strategy pattern is used to change an object’s behavior by selecting one of several interchangeable algorithms.
Template Pattern
Abstract class defines how to perform the executions, while derived classes implement the real executions.