design_pattern_composite

来源:互联网 发布:淘宝店主实拍 编辑:程序博客网 时间:2024/06/11 01:46

This post implement Composite Pattern in <Head First Design Patterns>.  The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

  1. Ensure that your problem is about representing "whole-part" hierarchical relationships.
  2. Consider the heuristic, "Containers that contain containees,each of which could be a container." For example, "Assemblies that contain components, each of which could be an assembly."Divide your domain concepts into container classes, and containee classes.
  3. Create a "lowest common denominator" interface that makes your containers and containees interchangeable. It should specify the behavior that needs to be exercised uniformly across all containee and container objects.
  4. All container and containee classes declare an "is a"relationship to the interface.
  5. All container classes declare a one-to-many "has a" relationship to the interface.
  6. Container classes leverage polymorphism to delegate to their containee objects.
  7. Child management methods [e.g. addChild(), removeChild()] should normally be defined in the Composite class. Unfortunately, the desire to treat Leaf and Composite objects uniformly may require that these methods be promoted to the abstract Component class. See the Gang of Four for a discussion of these "safety" versus "transparency" trade-offs.

The example in book is still menu, but this time, we have  submenu as menuitem

Note that the abstract interface MenuComponent defines all kinds of methods as pure virtual functions. However,  some of them are meaningless for a MenuItem (leaf), we need to raise exception once the method is called in leafs. For the nodes (Menu), we could implement those methods according to our plan.

#include<./exception.hpp>#include<vector>#include <algorithm>class MenuComponent {public:    virtual void add(MenuComponent* menuComponent) {throw new UnsupportedOperationException();}virtual void remove(MenuComponent* menuComponent) {throw new UnsupportedOperationException();}virtual MenuComponent* getChild(int i) {throw new UnsupportedOperationException();}virtual std::string getName() {throw new UnsupportedOperationException();}virtual std::string getDescription() {throw new UnsupportedOperationException();}virtual double getPrice() {throw new UnsupportedOperationException();}virtual bool isVegetarian() {throw new UnsupportedOperationException();}virtual void print() {throw new UnsupportedOperationException();}};class MenuItem : public MenuComponent {private:    std::string name;std::string description;bool vegetarian;double price;public:    MenuItem(std::string name, std::string description, bool vegetarian, double price) {this->name = name;this->description = description;this->vegetarian = vegetarian;this->price = price;}virtual std::string getName() { return name; }virtual std::string getDescription() { return description; }virtual double getPrice() { return price; }virtual bool isVegetarian() { return vegetarian; }virtual void print() {std::cout << "  " << getName().c_str();if (isVegetarian()) {std::cout << "(v)";}std::cout << ", " << getPrice() << std::endl;std::cout << "     -- " << getDescription().c_str() << std::endl;}};class Menu : public MenuComponent {private:     std::vector<MenuComponent*> menuComponents;std::string name;std::string description;  public:     Menu(std::string name, std::string description) {this->name = name;this->description = description;}  virtual void add(MenuComponent* menuComponent) {menuComponents.push_back(menuComponent);}  virtual void remove(MenuComponent* menuComponent) {std::remove(menuComponents.begin(), menuComponents.end(), menuComponent);}  virtual MenuComponent* getChild(int i) {return menuComponents[i];}  virtual std::string getName() { return name; } virtual std::string getDescription() { return description; }virtual void print() {std::cout << std::endl << getName().c_str();std::cout << ", " << getDescription().c_str() << std::endl;std::cout << "---------------------" << std::endl;  std::vector<MenuComponent*>::iterator itr = menuComponents.begin();while (itr != menuComponents.end()) {MenuComponent* menuComponent = *itr++;menuComponent->print();}}};
This time, we also define our own exception type

#include <exception>class UnsupportedOperationException : std::exception {public:    virtual const char* what() const throw(){        return "Undefined Operation!";    }};

The waitress class is very simple

class Waitress {private:    MenuComponent* allMenus;public:    Waitress(MenuComponent* allMenus) {this->allMenus = allMenus;} virtual void printMenu() {allMenus->print();}};
The main function is

#include <iostream>#include <./exception.hpp>#include <./menu.hpp>#include <./waitress.hpp>int main(){    MenuComponent* pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", "Breakfast");MenuComponent* dinerMenu = new Menu("DINER MENU", "Lunch");MenuComponent* cafeMenu = new Menu("CAFE MENU", "Dinner");MenuComponent* dessertMenu = new Menu("DESSERT MENU", "Dessert of course!");MenuComponent* coffeeMenu = new Menu("COFFEE MENU", "Stuff to go with your afternoon coffee");    MenuComponent* allMenus = new Menu("ALL MENUS", "All menus combined");    allMenus->add(pancakeHouseMenu);allMenus->add(dinerMenu);allMenus->add(cafeMenu);pancakeHouseMenu->add(new MenuItem("K&B's Pancake Breakfast","Pancakes with scrambled eggs, and toast",true,2.99));pancakeHouseMenu->add(new MenuItem("Regular Pancake Breakfast","Pancakes with fried eggs, sausage",false,2.99));pancakeHouseMenu->add(new MenuItem("Blueberry Pancakes","Pancakes made with fresh blueberries, and blueberry syrup",true,3.49));pancakeHouseMenu->add(new MenuItem("Waffles","Waffles, with your choice of blueberries or strawberries",true,3.59));dinerMenu->add(new MenuItem("Vegetarian BLT","(Fakin') Bacon with lettuce & tomato on whole wheat",true,2.99));dinerMenu->add(new MenuItem("BLT","Bacon with lettuce & tomato on whole wheat",false,2.99));dinerMenu->add(new MenuItem("Soup of the day","A bowl of the soup of the day, with a side of potato salad",false,3.29));dinerMenu->add(new MenuItem("Hotdog","A hot dog, with saurkraut, relish, onions, topped with cheese",false,3.05));dinerMenu->add(new MenuItem("Steamed Veggies and Brown Rice","Steamed vegetables over brown rice",true,3.99));dinerMenu->add(new MenuItem("Pasta","Spaghetti with Marinara Sauce, and a slice of sourdough bread",true,3.89));dinerMenu->add(dessertMenu);dessertMenu->add(new MenuItem("Apple Pie","Apple pie with a flakey crust, topped with vanilla icecream",true,1.59));dessertMenu->add(new MenuItem("Cheesecake","Creamy New York cheesecake, with a chocolate graham crust",true,1.99));dessertMenu->add(new MenuItem("Sorbet","A scoop of raspberry and a scoop of lime",true,1.89));cafeMenu->add(new MenuItem("Veggie Burger and Air Fries","Veggie burger on a whole wheat bun, lettuce, tomato, and fries",true,3.99));cafeMenu->add(new MenuItem("Soup of the day","A cup of the soup of the day, with a side salad",false,3.69));cafeMenu->add(new MenuItem("Burrito","A large burrito, with whole pinto beans, salsa, guacamole",true,4.29));cafeMenu->add(coffeeMenu);coffeeMenu->add(new MenuItem("Coffee Cake","Crumbly cake topped with cinnamon and walnuts",true,1.59));coffeeMenu->add(new MenuItem("Bagel","Flavors include sesame, poppyseed, cinnamon raisin, pumpkin",false,0.69));coffeeMenu->add(new MenuItem("Biscotti","Three almond or hazelnut biscotti cookies",true,0.89));    Waitress* waitress = new Waitress(allMenus);waitress->printMenu();    return 0;}

0 0
原创粉丝点击