Skip to content

Commit 1d4dda5

Browse files
committed
Add Composite Pattern project
1 parent 44448cb commit 1d4dda5

File tree

10 files changed

+280
-0
lines changed

10 files changed

+280
-0
lines changed

Code/CompositePattern/CMakeLists.txt

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
# set project name
4+
project(CompositePattern)
5+
6+
set(SOURCES
7+
include/MenuComponent.hpp
8+
include/MenuItem.hpp
9+
include/Menu.hpp
10+
src/MenuItem.cpp
11+
src/Menu.cpp
12+
src/main.cpp
13+
)
14+
add_executable(CompositePattern ${SOURCES})
15+
16+
target_include_directories(CompositePattern
17+
PRIVATE
18+
${PROJECT_SOURCE_DIR}/include
19+
)
20+

Code/CompositePattern/README.md

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Diner Menu and Sub-Menus
2+
3+
A common interface for Menu and Menu Items.
4+
5+
6+
```mermaid
7+
classDiagram
8+
direction LR
9+
10+
class MenuComponent {
11+
+getName()
12+
+getDescription()
13+
+getPrice()
14+
+isVegetarian()
15+
+print()
16+
+add(Component)
17+
+remove(Component)
18+
+getChild(int)
19+
}
20+
21+
class Waitress
22+
23+
class MenuItem {
24+
+getName()
25+
+getDescription()
26+
+getPrice()
27+
+isVegetarian()
28+
+print()
29+
}
30+
31+
class Menu {
32+
-menuComponents
33+
+getName()
34+
+getDescription()
35+
+print()
36+
+add(Component)
37+
+remove(Component)
38+
+getChild(int)
39+
}
40+
41+
Waitress --> MenuComponent
42+
43+
MenuComponent <|-- MenuItem
44+
MenuComponent <|-- Menu
45+
MenuComponent <-- Menu
46+
```
47+
48+
- MenuComponent represents the interface for both MenuItem and Menu, it is an abstract class because there will be default implementation of methods
49+
- The Waitress will only interact with MenuComponent
50+
- MenuItem overrides the methods that make sense for a menu item
51+
- Why do we need default implementations? If the leaf (MenuItem) or the composite (Menu) doesn't want to implement some of the methods, they can fall back on some basic behavior
52+
53+
## But this is not Single responsibility! What's happenin?
54+
55+
Yeah, its true. This patterns throws Single-Responsiblity principle out of the water. But it is trade-off with *Transparency*.
56+
Allowing the Component interface to contain child management operations and the leaf operations, a client can treat both composites and leaf nodes uniformly. It becomes transparent to the client.
57+
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
#include "MenuComponent.hpp"
3+
#include <vector>
4+
5+
using namespace std;
6+
7+
class Menu : public MenuComponent {
8+
public:
9+
Menu(string name, string description);
10+
~Menu() {}
11+
void add(MenuComponent* component);
12+
void remove(MenuComponent* component);
13+
MenuComponent* getChild(int i);
14+
15+
string getName();
16+
string getDescription();
17+
void print();
18+
private:
19+
vector<MenuComponent*> menuComponents;
20+
string name;
21+
string description;
22+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#pragma once
2+
#include<string>
3+
#include<stdexcept>
4+
5+
class MenuComponent {
6+
public:
7+
virtual ~MenuComponent() {}
8+
9+
// methods that make sense for both maybe
10+
std::string getName() {
11+
throw std::runtime_error("Operation is not supported");
12+
}
13+
14+
std::string getDescription() {
15+
throw std::runtime_error("Operation is not supported");
16+
}
17+
18+
double getPrice() {
19+
throw std::runtime_error("Operation is not supported");
20+
}
21+
22+
bool isVegetarian() {
23+
throw std::runtime_error("Operation is not supported");
24+
}
25+
26+
virtual void print() {
27+
throw std::runtime_error("Operation is not supported");
28+
}
29+
30+
// methods that make sense for Menu (composite)
31+
void add() {
32+
throw std::runtime_error("Operation is not supported");
33+
}
34+
35+
void remove() {
36+
throw std::runtime_error("Operation is not supported");
37+
}
38+
39+
MenuComponent getChild() {
40+
throw std::runtime_error("Operation is not supported");
41+
}
42+
private:
43+
44+
};
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
#include "MenuComponent.hpp"
3+
4+
using namespace std;
5+
6+
/*
7+
Leaf
8+
*/
9+
class MenuItem : public MenuComponent {
10+
public:
11+
12+
MenuItem(string name, string description, bool vegetarian, double price);
13+
~MenuItem() {}
14+
string getName();
15+
string getDescription();
16+
bool isVegetarian();
17+
double getPrice();
18+
void print();
19+
20+
private:
21+
string name;
22+
string description;
23+
bool vegetarian;
24+
double price;
25+
};

Code/CompositePattern/install.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cmake --debug-output -B build -S .
2+
cmake --build build

Code/CompositePattern/run.sh

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./build/CompositePattern

Code/CompositePattern/src/Menu.cpp

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "Menu.hpp"
2+
#include<iostream>
3+
#include<algorithm>
4+
5+
using namespace std;
6+
7+
Menu::Menu(string name, string description) {
8+
this->name = name;
9+
this->description = description;
10+
}
11+
12+
void Menu::add(MenuComponent* component) {
13+
this->menuComponents.push_back(component);
14+
}
15+
16+
void Menu::remove(MenuComponent* component) {
17+
vector<MenuComponent*>::iterator it = std::find(menuComponents.begin(), menuComponents.end(), component);
18+
if(it != menuComponents.end()) {
19+
menuComponents.erase(it);
20+
}
21+
}
22+
23+
MenuComponent* Menu::getChild(int i) {
24+
return this->menuComponents[i];
25+
}
26+
27+
string Menu::getName() {
28+
return name;
29+
}
30+
31+
string Menu::getDescription() {
32+
return description;
33+
}
34+
35+
void Menu::print() {
36+
cout << "------------------------------" << endl;
37+
cout << name << " - " << description << endl;
38+
cout << "------------------------------" << endl;
39+
for(auto it = menuComponents.begin(); it != menuComponents.end(); it++) {
40+
(*it)->print();
41+
}
42+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include "MenuItem.hpp"
2+
#include<iostream>
3+
4+
MenuItem::MenuItem(string name, string description, bool vegetarian, double price) {
5+
this->name = name;
6+
this->description = description;
7+
this->vegetarian = vegetarian;
8+
this->price = price;
9+
}
10+
11+
string MenuItem::getName() {
12+
return name;
13+
}
14+
15+
string MenuItem::getDescription() {
16+
return description;
17+
}
18+
19+
bool MenuItem::isVegetarian() {
20+
return vegetarian;
21+
}
22+
23+
double MenuItem::getPrice() {
24+
return price;
25+
}
26+
27+
void MenuItem::print() {
28+
cout << getName();
29+
if(isVegetarian()) {
30+
cout << " (v)";
31+
}
32+
cout << ", " << getPrice();
33+
cout << " - " << getDescription() << endl;
34+
}

Code/CompositePattern/src/main.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include<bits/stdc++.h>
2+
#include "Menu.hpp"
3+
#include "MenuItem.hpp"
4+
5+
using namespace std;
6+
7+
8+
int main() {
9+
Menu* dinerMenu = new Menu("Diner", "Delicious as always");
10+
11+
Menu* dinerSubMenu = new Menu("Diwali Special", "Celebrate the festival with great taste");
12+
dinerSubMenu->add(new MenuItem("Paneer Tikka", "very nice", true, 3.99));
13+
dinerSubMenu->add(new MenuItem("Chole Bhature", "very nice", true, 7.99));
14+
dinerSubMenu->add(new MenuItem("Deluxe Thali", "very nice", true, 12.99));
15+
dinerSubMenu->add(new MenuItem("Malai Chaap", "very nice", true, 6.99));
16+
17+
18+
dinerMenu->add(new MenuItem("Chicken 69", "the best we got", false, 9.99));
19+
dinerMenu->add(new MenuItem("Fish and Rice", "good ol' fish and rice", false, 16.99));
20+
dinerMenu->add(dinerSubMenu);
21+
22+
23+
dinerMenu->print();
24+
25+
cout << "-------------------------" << endl;
26+
cout << "DELETING SUB MENU" << endl;
27+
cout << "-------------------------" << endl;
28+
29+
dinerMenu->remove(dinerSubMenu);
30+
31+
dinerMenu->print();
32+
return 0;
33+
}

0 commit comments

Comments
 (0)