Javascript. Strategy pattern

Как известно, такой паттерн проектирования как Стратегия (Strategy) определяет семейство алгоритмов, инкапсулирует каждый из них и обеспечивает их взаимозаменяемость. Он позволяет модифицировать алгоритмы независимо от их использования на стороне клиента. Данный паттерн относится к паттернам поведения. Пример использования паттерна взят из книги - Э.Фримена, К.Сьерра, Б.Бейтс - Паттерны проектирования - с адаптацией под javascript. С идентичной реализацией на php можно ознакомиться по ссылке - PHP5. Композиция на примере паттерна Стратегия.

/* interface FlyBehavior - abstract Strategy of FlyBehavior */

var FlyBehavior = function () {
this.fly = function () {};
};

/* FlyWithWings - concrete Strategy of FlyBehavior */

var FlyWithWings = function () {
this.fly = function () {
console.log("I`m flying");
};
};

FlyWithWings.prototype = new FlyBehavior();
FlyWithWings.prototype.constructor = FlyWithWings;

/* FlyNoWay - concrete Strategy of FlyBehavior */

var FlyNoWay = function () {
this.fly = function () {
console.log("I can`t fly");
}
};

FlyNoWay.prototype = new FlyBehavior();
FlyNoWay.prototype.constructor = FlyNoWay;

/* FlyRocketPowered - concrete Strategy of FlyBehavior */

var FlyRocketPowered = function () {
this.fly = function () {
console.log("I`m flying with a rocket");
};
};

FlyRocketPowered.prototype = new FlyBehavior();
FlyRocketPowered.prototype.constructor = FlyRocketPowered;

/* interface QuackBehavior - abstract Strategy of QuackBehavior */

var QuackBehavior = function () {
this.quack = function () {};
};

/* Quack - concrete Strategy of QuackBehavior */

var Quack = function () {
this.quack = function () {
console.log("Quack");
}
};

Quack.prototype = new QuackBehavior();
Quack.prototype.constructor = Quack;

/* Squeak - concrete Strategy of QuackBehavior */

var Squeak = function () {
this.quack = function () {
console.log("Squeak");
}
};

Squeak.prototype = new QuackBehavior();
Squeak.prototype.constructor = Squeak;

/* MuteQuack - concrete Strategy of QuackBehavior */

var MuteQuack = function () {
this.quack = function () {
console.log("<< Silence >>");
}
};

MuteQuack.prototype = new QuackBehavior();
MuteQuack.prototype.constructor = MuteQuack;

/* Abstract Client of abstract FlyBehavior Strategy and abstract  QuackBehavior Strategy */

var Duck = function () {

var flyBehavior;
var quackBehavior;
// abstract method
this.display = function () {};
this.setFlyBehavior = function (fb) {
flyBehavior = fb;
};
this.setQuackBehavior = function (qb) {
quackBehavior = qb;
};
this.performFly = function () {
flyBehavior.fly();
};
this.performQuack = function () {
quackBehavior.quack();
};
this.swim = function () {
console.log("All ducks float, even decoys!");
};

};

/* Concrete Client of FlyWithWings Strategy and Quack Strategy */

var MallardDuck = function () {

this.setFlyBehavior(new FlyWithWings());
this.setQuackBehavior(new Quack());
this.display = function () {
console.log("I`m a real Mallard duck");
};

};

MallardDuck.prototype = new Duck();
MallardDuck.prototype.constructor = MallardDuck;

/* Concrete Client of FlyNoWay Strategy and Quack Strategy */

var ModelDuck = function () {

this.setFlyBehavior(new FlyNoWay());
this.setQuackBehavior(new Quack());

this.display = function () {
console.log("I`m a model duck");
};
};

ModelDuck.prototype = new Duck();
ModelDuck.prototype.constructor = ModelDuck;

/* test application */

var Application = function () {

this.run = function () {
var mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
var model = new ModelDuck();
model.performQuack();
model.performFly();
                // dynamic set new Concrete Strategy FlyRocketPowered 
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
};

};

var application = new Application();
application.run();

На выходе получаем следующие сообщения клиентов 

Quack
I`m flying

Quack
I can`t fly
I`m flying with a rocket

Ниже представлена схема реализации паттерна Стратегия (Strategy)