// open closed principle // open for extension, closed for modification #include #include #include using namespace std; enum class Color { Red, Green, Blue }; enum class Size {Small, Medium, Large }; struct Product { string name; Color color; Size size; }; struct ProductFilter { typedef vector Items; static Items by_color(Items items, Color color); static Items by_size(Items items, Size size) { Items result; for (auto& i : items) if (i->size == size) result.push_back(i); return result; } // size and color static Items by_color_and_size(Items items, Size size, Color color); // violated OCP b/c we had to jump in and change the underlying object // stable objects are easier to maintain }; ProductFilter::Items ProductFilter::by_color(Items items, Color color) { Items result; for (auto& i : items) if (i->color == color) result.push_back(i); return result; } ProductFilter::Items ProductFilter::by_color_and_size(Items items, Size size, Color color) { Items result; for (auto& i : items) if (i->size == size && i->color == color) result.push_back(i); return result; } template struct AndSpecification; template struct Specification { virtual bool is_satisfied(T* item) = 0; AndSpecification operator &&(Specification& other) { return AndSpecification(*this, other); } }; template struct Filter { virtual vector filter(vector items, Specification& spec) = 0; }; struct BetterFilter : Filter { vector filter(vector items, Specification& spec) override { vector result; for (auto& p : items) if (spec.is_satisfied(p)) result.push_back(p); return result; } }; struct ColorSpecification : Specification { Color color; explicit ColorSpecification(const Color color) : color{color} { } bool is_satisfied(Product* item) override { return item->color == color; } }; struct SizeSpecification : Specification { Size size; explicit SizeSpecification(const Size size) : size{ size } { } bool is_satisfied(Product* item) override { return item->size == size; } }; template struct AndSpecification : Specification { Specification& first; Specification& second; AndSpecification(Specification& first, Specification& second) : first{first}, second{second} { } bool is_satisfied(T* item) override { return first.is_satisfied(item) && second.is_satisfied(item); } }; int main12321() { Product apple{ "Apple", Color::Green, Size::Small }; Product tree{ "Tree", Color::Green, Size::Large }; Product house{ "House", Color::Blue, Size::Large }; vector all{ &apple, &tree, &house }; BetterFilter bf; ColorSpecification green(Color::Green); auto green_things = bf.filter(all, green); for (auto& x : green_things) cout << x->name << " is green" << endl; SizeSpecification big(Size::Large); //AndSpecification green_and_big{ big, green }; auto green_and_big = ColorSpecification(Color::Green) && SizeSpecification(Size::Large); auto big_green_things = bf.filter(all, green_and_big); for (auto& x : big_green_things) cout << x->name << " is big and green" << endl; getchar(); return 0; }