Last active
August 29, 2015 14:16
-
-
Save bassosimone/683bdce621b85aadae84 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ight/common/pointer.hpp> // SharedPointer: a std::shared_ptr wrapper with null pointer checks | |
using namespace ight::common::pointer; // Allow you to use SharedPointer directly | |
// An abstract class and two implementations of it | |
struct AbstractAntani { | |
// API: | |
virtual void foo() = 0; | |
virtual std::string bar(double) = 0; | |
virtual ~AbstractAntani() = 0; | |
// No copy and no move | |
AbstractAntani(AbstractAntani&) = delete; | |
AbstractAntani& operator=(AbstractAntani&) = delete; | |
AbstractAntani(AbstractAntani&&) = delete; | |
AbstractAntani& operator=(AbstractAntani&&) = delete; | |
} | |
struct SpecificAntani : public AbstractAntani { | |
virtual void foo() {} | |
virtual std::string bar(double) { return "xx" }; | |
virtual ~SpecificAntani() {} | |
} | |
struct AnotherAntani : public AbstractAntani { | |
virtual void foo() {} | |
virtual std::string bar(double) { return "x" }; | |
virtual ~SpecificAntani() {} | |
} | |
// Proxy pattern case #1 | |
// 1) you need to write more code (-) | |
// 2) you have a factory like constructor (-) | |
// 3) but usage is more intuitive (+) | |
class Antani { | |
SharedPointer<AbstractAntani> impl; | |
public: | |
Antani(std::map<std::string, std::string> options) { | |
if (options["type"] == "specific") { | |
impl = std::make_shared<SpecificAntani>(); | |
} else { | |
impl = std::make_shared<AnotherAntani>(); | |
} | |
} | |
virtual void foo() { impl->foo(); } | |
virtual std::string bar(double) { return impl->bar(); }; | |
virtual ~SpecificAntani() { /* nothing */; } | |
} | |
Antani foo{{"type", "specific"}}; | |
foo.foo(); | |
foo.bar(); | |
// Proxy pattern case #2 | |
// 1) you write less code (+) | |
// 2) construction is more verbose (-) | |
// 3) usage is through a pointer (-) | |
SharedPointer<AbstractAntani> foo = std::make_shared<AnotherAntani>(); | |
foo->foo(); | |
foo->bar(); | |
// 4) in the following case (and this is a bug of my | |
// implementation) you get a pointer without automatic | |
// null pointer check | |
auto foo = std::make_shared<AnotherAntani>(); | |
// The above problem could be fixed in the following two ways: | |
// A) add a make method to the wrapped pointer | |
auto foo = SharedPointer<AnotherAntani>(); // Empty shared pointer with null pointer checks | |
auto foo = SharedPointer<AnotherAntani>::make(); // Pointer to something | |
// B) more dangerous but more intuitive, you allow to set the pointer directly | |
auto foo = SharedPointer<AbstractAntani>(); | |
foo = new AnotherAntani(); | |
// C) same as B but using a standard method in C++'s shared_ptr | |
auto foo = SharedPointer<AbstractAntani>(); | |
foo.reset(new AnotherAntani()); | |
// Proxy pattern case #3: | |
// See https://gist.github.com/bassosimone/ebaf789cea61c11efb67 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment