Сегодня, копаясь в архивах, случайно нашел замечательную книгу
Eric Freeman "Head First Design Patterns".
Ощущения чем-то сродни тем, которые испытываешь от найденной на дачном чердаке книги во время уборки в жаркий летний день. С неожиданной находки сметаешь пыль и усевшись на каком-то старом хламе, с удовольствием начинаешь ее листать.
Быстро пробежал глазами первый паттерн "Стратегия", еще раз восхитившись тем, как толково и доступно все написано. Почему-то зацепила фраза о том, что для понимания сути примеров нужно как минимум знать Java или хотя бы С#. Ой, да ладно. А почему не C++ или Python? Я имею право на такую постановку вопроса, так как сейчас работаю в проекте, написанном на Java. Добрую часть карьеры я был иногда слишком "религиозен" насчет операционных систем и языков программирования, но затем понял, что не обязан приносить клятву верности только избранной технологии или языку и считать их лучшими, отметая остальные. Именно поэтому вместо популярных ныне Java и С# я в качестве развлечения реализовал описанный пример на C++:
коту программисту делать нечего, он удовольствия ради код с Жабы на Цэ Два Креста перепихивать станет!" :)
И что с этим делать? Удалить это все и забыть книгу до следующей "уборки на чердаке"? Решил оставить. Кто знает, может это все кому-нибудь пригодится, а если вдруг пригодится, то не забудьте слова "Банды четырех":
Ощущения чем-то сродни тем, которые испытываешь от найденной на дачном чердаке книги во время уборки в жаркий летний день. С неожиданной находки сметаешь пыль и усевшись на каком-то старом хламе, с удовольствием начинаешь ее листать.
Быстро пробежал глазами первый паттерн "Стратегия", еще раз восхитившись тем, как толково и доступно все написано. Почему-то зацепила фраза о том, что для понимания сути примеров нужно как минимум знать Java или хотя бы С#. Ой, да ладно. А почему не C++ или Python? Я имею право на такую постановку вопроса, так как сейчас работаю в проекте, написанном на Java. Добрую часть карьеры я был иногда слишком "религиозен" насчет операционных систем и языков программирования, но затем понял, что не обязан приносить клятву верности только избранной технологии или языку и считать их лучшими, отметая остальные. Именно поэтому вместо популярных ныне Java и С# я в качестве развлечения реализовал описанный пример на C++:
#include <iostream>
namespace hfstrategy {
class FlyBehavior {
public:
virtual void fly() = 0;
};
class FlyWithWings: public FlyBehavior {
public:
void fly() { std::cout << "I'm flying!!" << std::endl; }
};
class FlyRocketPowered: public FlyBehavior {
public:
void fly() { std::cout << "I'm flying with a rocket." << std::endl; }
};
class FlyNoWay: public FlyBehavior {
public:
void fly() { std::cout << "I can't fly." << std::endl; }
};
class QuackBehavior {
public:
virtual void quack() = 0;
};
class FakeQuack: public QuackBehavior {
public:
void quack() { std::cout << "Qwak" << std::endl; }
};
class MuteQuack: public QuackBehavior {
public:
void quack() { std::cout << "<< Silence >>" << std::endl; }
};
class Squeak: public QuackBehavior {
public:
void quack() { std::cout << "Squeak" << std::endl; }
};
class Quack: public QuackBehavior {
public:
void quack() { std::cout << "Quack" << std::endl; }
};
class Duck {
FlyBehavior *flyBehavior;
QuackBehavior *quackBehavior;
public:
Duck() { }
void setFlyBehavior (FlyBehavior *fb) { flyBehavior = fb; }
void setQuackBehavior(QuackBehavior *qb) { quackBehavior = qb; }
virtual void display() = 0;
void performFly() { flyBehavior->fly(); }
void performQuack() { quackBehavior->quack(); }
void swim() { std::cout << "All ducks float, even decoys!" << std::endl; }
};
class RubberDuck: public Duck {
public:
RubberDuck() {
FlyNoWay objf;
Squeak objq;
setFlyBehavior(&objf);
setQuackBehavior(&objq);
}
void display() { std::cout << "I'm a rubber duckie" << std::endl; }
};
class MallardDuck: public Duck {
public:
MallardDuck() {
FlyWithWings objf;
Quack objq;
setFlyBehavior(&objf);
setQuackBehavior(&objq);
}
void display() { std::cout << "I'm a real Mallard duck" << std::endl; }
};
class ModelDuck: public Duck {
public:
ModelDuck() {
FlyNoWay objf;
Quack objq;
setFlyBehavior(&objf);
setQuackBehavior(&objq);
}
void display() { std::cout << "I'm a model duck" << std::endl; }
};
class RedHeadDuck: public Duck {
public:
RedHeadDuck() {
FlyWithWings objf;
Quack objq;
setFlyBehavior(&objf);
setQuackBehavior(&objq);
}
void display() { std::cout << "I'm a real Red Headed duck" << std::endl; }
};
class DecoyDuck: public Duck {
public:
DecoyDuck() {
FlyNoWay objf;
MuteQuack objq;
setFlyBehavior(&objf);
setQuackBehavior(&objq);
}
void display() { std::cout << "I'm a duck Decoy" << std::endl; }
};
}
int main() {
using namespace hfstrategy;
Duck *ptrd;
RubberDuck rubberduck;
MallardDuck mallardduck;
ModelDuck modelduck;
RedHeadDuck redheadduck;
DecoyDuck decoyduck;
ptrd = &decoyduck;
ptrd->display();
ptrd->performFly();
ptrd->performQuack();
ptrd->swim();
return 0;
}
$ g++ -g -Wall -std=c++11 duck.cpp -o duck
$ ./duck.exe
I'm a duck Decoy
I can't fly.
<< Silence >>
All ducks float, even decoys!
Вот уж воистину точно сказано было: "Когда И что с этим делать? Удалить это все и забыть книгу до следующей "уборки на чердаке"? Решил оставить. Кто знает, может это все кому-нибудь пригодится, а если вдруг пригодится, то не забудьте слова "Банды четырех":
Зависимость от реализации может повлечь за собой проблемы при попытке повторного использования подкласса. Если хотя бы один аспект унаследованной реализации непригоден для новой предметной области, то приходится переписывать родительский класс или заменять его чем-то более подходящим. Такая зависимость ограничивает гибкость и возможности повторного использования. С проблемой можно справиться, если наследовать только абстрактным классам, поскольку в них обычно совсем нет реализации или она минимальна.Продолжение Паттерн "Стратегия": жаркое из питона.