var _hasProp = {}.hasOwnProperty,
_extends = function(child, parent) {
for (var key in parent) {
if (_hasProp.call(parent, key)) {
child[key] = parent[key];
}
}
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
};
// Component
var Component = (function () {
function Component(name) {
this.name = name || 'undefined';
}
Component.prototype.add = function () {};
Component.prototype.remove = function () {};
Component.prototype.display = function () {};
return Component;
})();
// Composite
var Composite = (function (_super) {
_extends(Composite, _super);
function Composite() {
this.children = [];
}
Composite.prototype.add = function (component) {
if (component instanceof Component) {
this.children.push(component);
}
};
Composite.prototype.remove = function (component) {
if (component instanceof Component) {
var index = this.children.indexOf(component);
if (~index) {
this.children.splice(index, 1);
}
}
};
Composite.prototype.display = function () {
console.log(this.children);
};
return Composite;
})(Component);
// Leaf
var Leaf = (function (_super) {
_extends(Leaf, _super);
function Leaf() {
return Leaf.__super__.constructor.apply(this, arguments);
}
Leaf.prototype.display = function() {
console.log("Cannot add to a leaf");
};
Leaf.prototype.display = function() {
console.log("Cannot remove from a leaf");
};
Leaf.prototype.display = function() {
console.log(this.name);
};
return Leaf;
})(Component);
var root = new Composite('root');
root.add(new Leaf('Leaf A'));
root.add(new Leaf('Leaf B'));
var comp = new Composite('Composite X');
comp.add(new Leaf('Leaf XA'));
comp.add(new Leaf('Leaf XB'));
comp.add(new Leaf('Leaf XC'));
comp.add(new Leaf('Leaf XD'));
root.add(comp);
root.add(new Leaf('Leaf C'));
var leaf = new Leaf('Leaf D');
root.add(leaf);
root.remove(comp);
root.remove(leaf);
root.display();
Вот еще один пример реализации данного паттерна. Стоит только оговориться: паттерн Компоновщик ниже реализован с использованием паттерна Итератор (см. здесь).
Array.prototype.iterator = function () {
var self = this, position = 0, undefined;
return {
next:function () {
return self[position++];
},
hasNext: function () {
if (position >= self.length) {
return false;
}
else {
return true;
}
},
remove: function () {
if (position <= 0) {
throw new Error("You can`t an item until you`ve done at least one next()");
}
if (self[position - 1] !== undefined) {
for (var i = position - 1; i < (self.length - 1); i++) {
self[i] = self[i + 1];
}
self[self.length - 1] = undefined;
}
}
};
};
/* abstract class MenuComponent */
var MenuComponent = function () {
this.add = function (menuComponent) {
throw new Error("UnsupportedOperationException");
};
this.remove = function (menuComponent) {
throw new Error("UnsupportedOperationException");
};
this.getChild = function (i) {
throw new Error("UnsupportedOperationException");
};
this.getName = function () {
throw new Error("UnsupportedOperationException");
};
this.getDescription = function () {
throw new Error("UnsupportedOperationException");
};
this.getPrice = function () {
throw new Error("UnsupportedOperationException");
};
this.isVegetarian = function () {
throw new Error("UnsupportedOperationException");
};
this.print = function () {
throw new Error("UnsupportedOperationException");
};
}
/* Menu Leaf */
var MenuItem = function (name, description, vegetarian, price) {
var name = name,
description = description,
vegetarian = vegetarian,
price = price;
this.getName = function () {
return name;
};
this.getDescription = function () {
return description;
};
this.getPrice = function () {
return price;
};
this.isVegetarian = function () {
return vegetarian;
};
this.print = function () {
var item = " " + this.getName() +
(this.isVegetarian() ? "(v)" : "") +
", " + this.getPrice() +
" -- " + this.getDescription();
console.log(item);
};
};
MenuItem.prototype = new MenuComponent();
MenuItem.prototype.constructor = MenuItem;
/* Menu Composite */
var Menu = function (name, description) {
var menuComponents = [],
name = name,
description = description;
this.add = function (menuComponent) {
menuComponents.push(menuComponent);
};
this.remove = function (menuComponent) {
var index = menuComponents.indexOf(menuComponent);
if (index >= 0) {
menuComponents.splice(index, 1);
};
};
this.getChild = function (i) {
return menuComponents[i];
};
this.getName = function () {
return name;
};
this.getDescription = function () {
return description;
};
this.print = function () {
var item = this.getName() + ", " + this.getDescription();
console.log(item);
console.log("----------------------");
var iterator = menuComponents.iterator();
while (iterator.hasNext()) {
var menuComponent = iterator.next();
menuComponent.print();
}
};
};
Menu.prototype = new MenuComponent();
Menu.prototype.constructor = Menu;
/* Client */
var Waitress = function (allMenus) {
var allMenus = allMenus;
this.printMenu = function () {
allMenus.print();
};
};
/* test application */
var Application = function () {
this.run = function () {
var pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", "Breakfast"),
dinerMenu = new Menu("DINER MENU", "Lunch"),
cafeMenu = new Menu("CAFE MENU", "Dinner"),
dessertMenu = new Menu("DESSERT MENU", "Dessert of course!");
var 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", 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 whle wheat", true, 2.99));
dinerMenu.add(new MenuItem("BLT", "Bacon with lettuce & tomato on whle wheat", false, 2.99));
dinerMenu.add(new MenuItem("Soup of the day", "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("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));
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));
var waitress = new Waitress(allMenus);
waitress.printMenu();
};
};
var application = new Application();
application.run();
На выходе имеем:
ALL MENUS, All menus combined
----------------------
PANCAKE HOUSE MENU, Breakfast
----------------------
K&B`s Pancake Breakfast(v), 2.99 -- Pancakes with scrambled eggs, and toast
Regular Pancake Breakfast, 2.99 -- Pancakes with fried eggs, sausage
Blueberry Pancakes(v), 3.49 -- Pancakes made with fresh blueberries
Waffles(v), 3.59 -- Waffles, with your choice of blueberries or strawberries
DINER MENU, Lunch
----------------------
Vegetarian BLT(v), 2.99 -- (Fakin) Bacon with lettuce & tomato on whle wheat
BLT, 2.99 -- Bacon with lettuce & tomato on whle wheat
Soup of the day, 3.29 -- Soup of the day, with a side of potato salad
Hotdog, 3.05 -- A hot dog, with saurkraut, relish, onions, topped with cheese
Pasta(v), 3.89 -- Spaghetti with Marinara Sauce, and a slice of sourdough bread
DESSERT MENU, Dessert of course!
----------------------
Apple Pie(v), 1.59 -- Apple pie with a flakey crust, topped with vanilla icecream
CAFE MENU, Dinner
----------------------
Veggie Burger and Air Fries(v), 3.99 -- Veggie burger on a whole wheat bun, lettuce, tomato, and fries
Soup of the day, 3.69 -- A cup of the soup of the day, with a side salad
Burrito(v), 4.29 -- A large burrito, with whole pinto beans, salsa, guacamole
Вот еще один пример реализации данного паттерна. Стоит только оговориться: паттерн Компоновщик ниже реализован с использованием паттерна Итератор (см. здесь).
Array.prototype.iterator = function () {
var self = this, position = 0, undefined;
return {
next:function () {
return self[position++];
},
hasNext: function () {
if (position >= self.length) {
return false;
}
else {
return true;
}
},
remove: function () {
if (position <= 0) {
throw new Error("You can`t an item until you`ve done at least one next()");
}
if (self[position - 1] !== undefined) {
for (var i = position - 1; i < (self.length - 1); i++) {
self[i] = self[i + 1];
}
self[self.length - 1] = undefined;
}
}
};
};
/* abstract class MenuComponent */
var MenuComponent = function () {
this.add = function (menuComponent) {
throw new Error("UnsupportedOperationException");
};
this.remove = function (menuComponent) {
throw new Error("UnsupportedOperationException");
};
this.getChild = function (i) {
throw new Error("UnsupportedOperationException");
};
this.getName = function () {
throw new Error("UnsupportedOperationException");
};
this.getDescription = function () {
throw new Error("UnsupportedOperationException");
};
this.getPrice = function () {
throw new Error("UnsupportedOperationException");
};
this.isVegetarian = function () {
throw new Error("UnsupportedOperationException");
};
this.print = function () {
throw new Error("UnsupportedOperationException");
};
}
/* Menu Leaf */
var MenuItem = function (name, description, vegetarian, price) {
var name = name,
description = description,
vegetarian = vegetarian,
price = price;
this.getName = function () {
return name;
};
this.getDescription = function () {
return description;
};
this.getPrice = function () {
return price;
};
this.isVegetarian = function () {
return vegetarian;
};
this.print = function () {
var item = " " + this.getName() +
(this.isVegetarian() ? "(v)" : "") +
", " + this.getPrice() +
" -- " + this.getDescription();
console.log(item);
};
};
MenuItem.prototype = new MenuComponent();
MenuItem.prototype.constructor = MenuItem;
/* Menu Composite */
var Menu = function (name, description) {
var menuComponents = [],
name = name,
description = description;
this.add = function (menuComponent) {
menuComponents.push(menuComponent);
};
this.remove = function (menuComponent) {
var index = menuComponents.indexOf(menuComponent);
if (index >= 0) {
menuComponents.splice(index, 1);
};
};
this.getChild = function (i) {
return menuComponents[i];
};
this.getName = function () {
return name;
};
this.getDescription = function () {
return description;
};
this.print = function () {
var item = this.getName() + ", " + this.getDescription();
console.log(item);
console.log("----------------------");
var iterator = menuComponents.iterator();
while (iterator.hasNext()) {
var menuComponent = iterator.next();
menuComponent.print();
}
};
};
Menu.prototype = new MenuComponent();
Menu.prototype.constructor = Menu;
/* Client */
var Waitress = function (allMenus) {
var allMenus = allMenus;
this.printMenu = function () {
allMenus.print();
};
};
/* test application */
var Application = function () {
this.run = function () {
var pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", "Breakfast"),
dinerMenu = new Menu("DINER MENU", "Lunch"),
cafeMenu = new Menu("CAFE MENU", "Dinner"),
dessertMenu = new Menu("DESSERT MENU", "Dessert of course!");
var 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", 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 whle wheat", true, 2.99));
dinerMenu.add(new MenuItem("BLT", "Bacon with lettuce & tomato on whle wheat", false, 2.99));
dinerMenu.add(new MenuItem("Soup of the day", "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("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));
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));
var waitress = new Waitress(allMenus);
waitress.printMenu();
};
};
var application = new Application();
application.run();
На выходе имеем:
ALL MENUS, All menus combined
----------------------
PANCAKE HOUSE MENU, Breakfast
----------------------
K&B`s Pancake Breakfast(v), 2.99 -- Pancakes with scrambled eggs, and toast
Regular Pancake Breakfast, 2.99 -- Pancakes with fried eggs, sausage
Blueberry Pancakes(v), 3.49 -- Pancakes made with fresh blueberries
Waffles(v), 3.59 -- Waffles, with your choice of blueberries or strawberries
DINER MENU, Lunch
----------------------
Vegetarian BLT(v), 2.99 -- (Fakin) Bacon with lettuce & tomato on whle wheat
BLT, 2.99 -- Bacon with lettuce & tomato on whle wheat
Soup of the day, 3.29 -- Soup of the day, with a side of potato salad
Hotdog, 3.05 -- A hot dog, with saurkraut, relish, onions, topped with cheese
Pasta(v), 3.89 -- Spaghetti with Marinara Sauce, and a slice of sourdough bread
DESSERT MENU, Dessert of course!
----------------------
Apple Pie(v), 1.59 -- Apple pie with a flakey crust, topped with vanilla icecream
CAFE MENU, Dinner
----------------------
Veggie Burger and Air Fries(v), 3.99 -- Veggie burger on a whole wheat bun, lettuce, tomato, and fries
Soup of the day, 3.69 -- A cup of the soup of the day, with a side salad
Burrito(v), 4.29 -- A large burrito, with whole pinto beans, salsa, guacamole