trainings/CreatingReliableSoftwareCpp/Presentation/examples/strategy/strategy2.cpp

168 lines
No EOL
5.2 KiB
C++

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
#include <set>
#include <vector>
class Ammunition {
public:
Ammunition(size_t amount)
: _amount(amount) {}
virtual ~Ammunition() = default;
virtual void fire() = 0;
virtual void draw() = 0;
virtual int getDamage() const = 0;
size_t amount() const { return _amount; }
private:
size_t _amount = 0;
};
class ChainShot;
class RoundShot;
class GrapeShot;
class FireStrategy {
public:
virtual void fire(const ChainShot& shot) = 0;
virtual void fire(const RoundShot& shot) = 0;
virtual void fire(const GrapeShot& shot) = 0;
};
class SDLFireStrategy : public FireStrategy {
public:
void fire(const ChainShot& shot) override;
void fire(const RoundShot& shot) override;
void fire(const GrapeShot& shot) override;
};
class WAMFireStrategy : public FireStrategy {
public:
void fire(const ChainShot& shot) override;
void fire(const RoundShot& shot) override;
void fire(const GrapeShot& shot) override;
};
class DrawStrategy {
public:
virtual void draw(const ChainShot& shot) = 0;
virtual void draw(const RoundShot& shot) = 0;
virtual void draw(const GrapeShot& shot) = 0;
};
class OpenGLDrawStrategy : public DrawStrategy {
public:
void draw(const ChainShot& shot) override;
void draw(const RoundShot& shot) override;
void draw(const GrapeShot& shot) override;
};
class MetalDrawStrategy : public DrawStrategy {
public:
void draw(const ChainShot& shot) override;
void draw(const RoundShot& shot) override;
void draw(const GrapeShot& shot) override;
};
class RoundShot : public Ammunition {
public:
RoundShot(size_t amount, std::unique_ptr<FireStrategy>&& fireStrategy, std::unique_ptr<DrawStrategy>&& drawStrategy)
: Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {}
void fire() override {
_fireStrategy->fire(*this /* other args if needed*/);
}
void draw() override {
_drawStrategy->draw(*this /* other args if needed*/);
}
int getDamage() const override { return 10; }
private:
std::unique_ptr<FireStrategy> _fireStrategy;
std::unique_ptr<DrawStrategy> _drawStrategy;
};
class ChainShot : public Ammunition {
public:
ChainShot(size_t amount, std::unique_ptr<FireStrategy>&& fireStrategy, std::unique_ptr<DrawStrategy>&& drawStrategy)
: Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {}
void fire() override {
_fireStrategy->fire(*this /* other args if needed*/);
}
void draw() override {
_drawStrategy->draw(*this /* other args if needed*/);
}
int getDamage() const override { return 15; }
private:
std::unique_ptr<FireStrategy> _fireStrategy;
std::unique_ptr<DrawStrategy> _drawStrategy;
};
class GrapeShot : public Ammunition {
public:
GrapeShot(size_t amount, std::unique_ptr<FireStrategy>&& fireStrategy, std::unique_ptr<DrawStrategy>&& drawStrategy)
: Ammunition(amount), _fireStrategy(std::move(fireStrategy)), _drawStrategy(std::move(drawStrategy)) {}
void fire() override {
_fireStrategy->fire(*this /* other args if needed*/);
}
void draw() override {
_drawStrategy->draw(*this /* other args if needed*/);
}
int getDamage() const override { return 20; }
private:
std::unique_ptr<FireStrategy> _fireStrategy;
std::unique_ptr<DrawStrategy> _drawStrategy;
};
void SDLFireStrategy::fire(const ChainShot& shot) {
std::cout << "SDL Chain Shot Deal: " << shot.getDamage() << " damage!" << '\n';
}
void SDLFireStrategy::fire(const RoundShot& shot) {
std::cout << "SDL Round Shot Deal: " << shot.getDamage() << " damage!" << '\n';
}
void SDLFireStrategy::fire(const GrapeShot& shot) {
std::cout << "SDL Grape Shot Deal: " << shot.getDamage() << " damage!" << '\n';
}
void WAMFireStrategy::fire(const ChainShot& shot) {
std::cout << "WAM Chain Shot Deal: " << shot.getDamage() << " damage!" << '\n';
}
void WAMFireStrategy::fire(const RoundShot& shot) {
std::cout << "WAM Round Shot Deal: " << shot.getDamage() << " damage!" << '\n';
}
void WAMFireStrategy::fire(const GrapeShot& shot) {
std::cout << "WAM Grape Shot Deal: " << shot.getDamage() << " damage!" << '\n';
}
void OpenGLDrawStrategy::draw(const ChainShot& shot) {
std::cout << "OpenGL Chain Shot: " << shot.amount() << '\n';
}
void OpenGLDrawStrategy::draw(const RoundShot& shot) {
std::cout << "OpenGL Round Shot: " << shot.amount() << '\n';
}
void OpenGLDrawStrategy::draw(const GrapeShot& shot) {
std::cout << "OpenGL Grape Shot: " << shot.amount() << '\n';
}
void MetalDrawStrategy::draw(const ChainShot& shot) {
std::cout << "Metal Chain Shot: " << shot.amount() << '\n';
}
void MetalDrawStrategy::draw(const RoundShot& shot) {
std::cout << "Metal Round Shot: " << shot.amount() << '\n';
}
void MetalDrawStrategy::draw(const GrapeShot& shot) {
std::cout << "Metal Grape Shot: " << shot.amount() << '\n';
}
int main() {
std::unique_ptr<Ammunition> grapeShot = std::make_unique<GrapeShot>(
100, std::make_unique<SDLFireStrategy>(), std::make_unique<OpenGLDrawStrategy>());
grapeShot->fire();
grapeShot->draw();
}