28.11.2023
JavaScript-OOP
JavaScript
JS Patterns
patterns.js #
/*
https://blog.carlosrojas.dev/quick-reference-guide-to-design-patterns-in-js-1ebeb1e1c605
*/
/* Singleton */
class Animal {
constructor() {
if (typeof Animal.instance === 'object') {
return Animal.instance;
}
Animal.instance = this;
return this;
}
}
export default Animal;
/* Prototype */
class Fruit {
constructor(name, weight) {
this.name = name;
this.weight = weight;
}
clone() {
return new Fruit(this.name, this.weight);
}
}
export default Fruit;
const apple = new Fruit('Apple', 150);
const clonedApple = apple.clone();
console.log(apple); // Originální ovoce
console.log(clonedApple); // Klonované ovoce
/* Factory */
class MovieFactory {
create(genre) {
if (genre === 'Adventure') return new Movie(genre, 10000);
if (genre === 'Action') return new Movie(genre, 11000);
}
}
class Movie {
constructor(type, price) {
this.type = type;
this.price = price;
}
}
export default MovieFactory;
/* Abstract Factory */
function foodProducer(kind) {
if (kind === 'protein') return proteinPattern;
if (kind === 'fat') return fatPattern;
return carbohydratesPattern;
}
function proteinPattern() {
return new Protein();
}
function fatPattern() {
return new Fat();
}
function carbohydratesPattern() {
return new Carbohydrates();
}
class Protein {
info() {
return 'I am Protein.';
}
}
class Fat {
info() {
return 'I am Fat.';
}
}
class Carbohydrates {
info() {
return 'I am carbohydrates.';
}
}
export default foodProducer;
/* Adapter */
class Soldier {
constructor(level) {
this.level = level;
}
attack() {
return this.level * 1;
}
}
class SuperSoldier {
constructor(level) {
this.level = level;
}
attackWithShield() {
return this.level * 10;
}
}
class SoldierAdapter {
constructor(superSoldier) {
this.superSoldier = superSoldier;
}
attack() {
return this.superSoldier.attackWithShield();
}
}
export { Soldier, SuperSoldier, SoldierAdapter };
// Vytvoření instance SuperSoldier
const superSoldier = new SuperSoldier(5);
// Vytvoření instance SoldierAdapter, který přijímá SuperSoldier jako argument
const soldierAdapter = new SoldierAdapter(superSoldier);
// Volání metody attack() na SoldierAdapteru, která skutečně volá attackWithShield() u SuperSoldiera
const result = soldierAdapter.attack();
console.log(result); // Vypíše: 50 (5 * 10)
/* Bridge */
class Soldier {
constructor(weapon) {
this.weapon = weapon;
}
}
class SuperSoldier extends Soldier {
constructor(weapon) {
super(weapon);
}
attack() {
return 'SuperSoldier, Weapon: ' + this.weapon.get();
}
}
class IronMan extends Soldier {
constructor(weapon) {
super(weapon);
}
attack() {
return 'Ironman, Weapon: ' + this.ink.get();
}
}
class Weapon {
constructor(type) {
this.type = type;
}
get() {
return this.type;
}
}
class Shield extends Weapon {
constructor() {
super('shield');
}
}
class Rocket extends Weapon {
constructor() {
super('rocket');
}
}
export { SuperSoldier, IronMan, Shield, Rocket };
// Vytvoření instancí zbraní
const shield = new Shield();
const rocket = new Rocket();
// Vytvoření instancí vojáků s různými zbraněmi
const superSoldier = new SuperSoldier(shield);
const ironMan = new IronMan(rocket);
// Útoky vojáků
console.log(superSoldier.attack()); // Vypíše: SuperSoldier, Weapon: shield
console.log(ironMan.attack()); // Vypíše: Ironman, Weapon: rocket
/* Composite */
//Equipment
class Equipment {
getPrice() {
return this.price || 0;
}
getName() {
return this.name;
}
setName(name) {
this.name = name;
}
}
class Pattern extends Equipment {
constructor() {
super();
this.equipments = [];
}
add(equipment) {
this.equipments.push(equipment);
}
getPrice() {
return this.equipments
.map(equipment => {
return equipment.getPrice();
})
.reduce((a, b) => {
return a + b;
});
}
}
class Cabbinet extends Pattern {
constructor() {
super();
this.setName('cabbinet');
}
}
// --- leafs ---
class FloppyDisk extends Equipment {
constructor() {
super();
this.setName('Floppy Disk');
this.price = 70;
}
}
class HardDrive extends Equipment {
constructor() {
super();
this.setName('Hard Drive');
this.price = 250;
}
}
class Memory extends Equipment {
constructor() {
super();
this.setName('Memory');
this.price = 280;
}
}
export { Cabbinet, FloppyDisk, HardDrive, Memory };
// Vytvoření jednotlivých listových tříd (FloppyDisk, HardDrive, Memory)
const floppyDisk = new FloppyDisk();
const hardDrive = new HardDrive();
const memory = new Memory();
// Vytvoření skříně a přidání jednotlivých listových tříd do skříně
const cabbinet = new Cabbinet();
cabbinet.add(floppyDisk);
cabbinet.add(hardDrive);
cabbinet.add(memory);
// Získání celkové ceny skříně
const totalPrice = cabbinet.getPrice();
console.log(`Total Price: ${totalPrice}`); // Vypíše: Total Price: 600
/* Decorator */
class Notification {
constructor(kind) {
this.kind = kind || "Generic";
}
getInfo() {
return `I'm a ${this.kind} Notification`;
}
}
class FacebookNotification extends Notification {
constructor() {
super("Facebook");
}
setNotification(msg) {
this.message = msg;
}
getInfo() {
return `${super.getInfo()} with the message: ${this.message}`;
}
}
class SMSNotification extends Notification {
constructor() {
super("SMS");
}
getInfo() {
return super.getInfo();
}
}
export { FacebookNotification, SMSNotification };
// Vytvoření instance SMSNotification
const smsNotification = new SMSNotification();
// Dekorace SMSNotification pomocí FacebookNotificationDecorator
const decoratedNotification = new FacebookNotificationDecorator(smsNotification);
// Získání informací o dekorované notifikaci
console.log(decoratedNotification.getInfo());
// Vypíše: I'm a SMS Notification decorated with Facebook feature
/* Facade */
class Cart {
constructor() {
this.discount = new Discount();
this.shipping = new Shipping();
this.fees = new Fees();
}
calc(price) {
price = this.discount.calc(price);
price = this.fees.calc(price);
price += this.shipping.calc();
return price;
}
}
class Discount {
calc(value) {
return value * 0.85;
}
}
class Shipping {
calc() {
return 500;
}
}
class Fees {
calc(value) {
return value * 1.1;
}
}
export default Cart;
/* FlyWeight */
class Ingredient {
constructor(name) {
this.name = name;
}
getInfo() {
return `I'm a ${this.name}`
}
}
class Ingredients {
constructor() {
this.ingredients = {};
}
create(name) {
let ingredient = this.ingredients[name];
if (ingredient) return ingredient;
this.ingredients[name] = new Ingredient(name);
return this.ingredients[name];
}
}
export { Ingredients };
/* Proxy */
class Plane {
fly() {
return 'flying';
}
}
class PilotProxy {
constructor(pilot) {
this.pilot = pilot;
}
fly() {
return this.pilot.age < 18 ? `too young to fly` : new Plane().fly();
}
}
class Pilot {
constructor(age) {
this.age = age;
}
}
export { Plane, PilotProxy, Pilot };
/* Iterator */
class Iterator {
constructor(el) {
this.index = 0;
this.elements = el;
}
next() {
return this.elements[this.index++];
}
hasNext() {
return this.index < this.elements.length;
}
}
export default Iterator;
// Importujte váš Iterator
import Iterator from './Iterator';
// Vytvořte nějakou kolekci dat (v tomto případě pole).
const collection = ['Prvek 1', 'Prvek 2', 'Prvek 3'];
// Vytvořte instanci Iteratoru, předávejte kolekci jako argument konstruktoru.
const iterator = new Iterator(collection);
// Projděte kolekci pomocí Iteratoru.
while (iterator.hasNext()) {
const element = iterator.next();
console.log(element);
}
/* Mediator */
class TrafficTower {
constructor() {
this.airplanes = [];
}
getPositions() {
return this.airplanes.map(airplane => {
return airplane.position.showPosition();
});
}
}
class Airplane {
constructor(position, trafficTower) {
this.position = position;
this.trafficTower = trafficTower;
this.trafficTower.airplanes.push(this);
}
getPositions() {
return this.trafficTower.getPositions();
}
}
class Position {
constructor(x,y) {
this.x = x;
this.y = y;
}
showPosition() {
return `My Position is ${x} and ${y}`;
}
}
export { TrafficTower, Airplane, Position };
const trafficTower = new TrafficTower();
const airplane1 = new Airplane(new Position(10, 20), trafficTower);
const airplane2 = new Airplane(new Position(30, 40), trafficTower);
// Informovat TrafficTower o pozici letadla.
airplane1.getPositions();
// Získat informace o pozicích ostatních letadel pomocí TrafficTower.
airplane2.getPositions();
/* State */
class OrderStatus {
constructor(name, nextStatus) {
this.name = name;
this.nextStatus = nextStatus;
}
next() {
return new this.nextStatus();
}
}
class WaitingForPayment extends OrderStatus {
constructor() {
super('waitingForPayment', Shipping);
}
}
class Shipping extends OrderStatus {
constructor() {
super('shipping', Delivered);
}
}
class Delivered extends OrderStatus {
constructor() {
super('delivered', Delivered);
}
}
class Order {
constructor() {
this.state = new WaitingForPayment();
}
nextPattern() {
this.state = this.state.next();
}
}
export default Order;
// Vytvořte instanci objednávky
const order = new Order();
// Zjistěte aktuální stav
console.log(order.state.name); // Výstup: 'waitingForPayment'
// Přejděte na další stav
order.nextPattern();
// Zjistěte nový stav
console.log(order.state.name); // Výstup: 'shipping'
// Přejděte na další stav
order.nextPattern();
// Zjistěte nový stav
console.log(order.state.name); // Výstup: 'delivered'
/* Strategy */
class ShoppingCart {
constructor(discount) {
this.discount = discount;
this.amount = 0;
}
checkout() {
return this.discount(this.amount);
}
setAmount(amount) {
this.amount = amount;
}
}
function guest(amount) {
return amount;
}
function regular(amount) {
return amount * 0.9;
}
function premium(amount) {
return amount * 0.8;
}
export { ShoppingCart, guest, regular, premium };
// Importujte třídu ShoppingCart a slevové strategie
import { ShoppingCart, guest, regular, premium } from './ShoppingCart';
// Vytvořte instanci nákupního košíku s různými slevovými strategiemi
const cartGuest = new ShoppingCart(guest);
const cartRegular = new ShoppingCart(regular);
const cartPremium = new ShoppingCart(premium);
// Nastavte množství v košíku
cartGuest.setAmount(100);
cartRegular.setAmount(100);
cartPremium.setAmount(100);
// Proveďte platbu s různými slevovými strategiemi
console.log(cartGuest.checkout()); // Výstup: 100 (žádná sleva)
console.log(cartRegular.checkout()); // Výstup: 90 (10% sleva pro běžného zákazníka)
console.log(cartPremium.checkout()); // Výstup: 80 (20% sleva pro prémiového zákazníka)
/* Template */
class Tax {
calc(value) {
if (value >= 1000) value = this.overThousand(value);
return this.complementaryFee(value);
}
complementaryFee(value) {
return value + 10;
}
}
class VAT extends Tax {
constructor() {
super();
}
overThousand(value) {
return value * 1.1;
}
}
class GST extends Tax {
constructor() {
super();
}
overThousand(value) {
return value * 1.2;
}
}
export { VAT, GST };
// Importujte třídy VAT a GST
import { VAT, GST } from './Tax';
// Vytvořte instanci třídy VAT a provedte výpočet daně
const vatTax = new VAT();
console.log(vatTax.calc(1200)); // Výstup: 1320 (včetně přirážky pro hodnoty nad 1000)
// Vytvořte instanci třídy GST a provedte výpočet daně
const gstTax = new GST();
console.log(gstTax.calc(1200)); // Výstup: 1440 (včetně přirážky pro hodnoty nad 1000)