#include #include using namespace std; class Texture { public: Texture() = default; virtual ~Texture() = default; virtual const string& show_texture() = 0; }; class Shape { protected: shared_ptr t; public: Shape(shared_ptr t) : t(t) {} virtual void draw() = 0; }; class Square : public Shape { int x1; int y1; int x2; int y2; public: Square(shared_ptr t, int x1, int y1, int x2, int y2) : Shape(t), x1(x1), y1(y1), x2(x2), y2(y2) {} virtual void draw() { // Maybe you have to use different show_texture. For example, // show_texture_square for Square, show_texture_circle for Circle, // so that the actions is M*N, but that is unavoidable, and the // class's count is M+N. cout << "draw square: " << x1 << " " << y1 << " " << x2 << " " << y2 << " with texture " << t->show_texture() << endl; } }; class Circle : public Shape { int x; int y; int r; public: Circle(shared_ptr t, int x, int y, int r) : Shape(t), x(x), y(y), r(r) {} virtual void draw() override { cout << "draw circle: " << x << " " << y << " " << r << " with texture " << t->show_texture() << endl; } }; class SoilTexture : public Texture { string s; public: SoilTexture(int level) : s("Soil") { s += to_string(level); } virtual const string& show_texture() override { return s; } }; class WaterTexture : public Texture { string s; public: WaterTexture(int level) : s("Water") { s += to_string(level + 256); } virtual const string& show_texture() override { return s; } }; int main() { shared_ptr ts = make_shared(123); shared_ptr tw = make_shared(11); // When you want to create a new texture, you just need to create one // texture class and use it when generating shape. // you don't need to create a set of shapes. // You can switch different Textures esaily when running. auto c = make_shared(ts, 1, 2, 3); auto s = make_shared(tw, 1, 2, 3, 4); c->draw(); s->draw(); }