Created
August 17, 2014 20:02
-
-
Save jackbergus/0ae0b0e6c81617d9876f to your computer and use it in GitHub Desktop.
A variant of the repository pattern
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
/* | |
* Repository-MonoView.cpp | |
* This file is part of <program name> | |
* | |
* Copyright (C) 2014 - Giacomo Bergami | |
* | |
* <program name> is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* <program name> is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with <program name>. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#include <vector> | |
#include <memory> | |
#include <iostream> | |
//////////////////////////////////////////////////////////////////////////////// | |
// Pattern: Repository-MonoView | |
// A variant of the visitor pattern | |
// | |
// Repository (client): stores in a local data structure. We want that repository's | |
// changes could be reported by remote objects that holds a reference to a | |
// repository's resource. | |
// Each remote object should have a WeakReference object, in order to notify the | |
// repository of its destruction. | |
// | |
// In order to do this, there is a WeakHolder, which is an Observer of the | |
// remote's object destruction and Observable by WeakHolder itself when changes | |
// are submitted. | |
// | |
// WeakReference is also an Observer of a local Repository's change | |
// | |
// The aim of such pattern is to not store remotely the value of the repository, | |
// but to change only its coordinates. | |
//////////////////////////////////////////////////////////////////////////////// | |
// Header | |
template <typename T> class WeakReference; | |
template <typename T> class Repository; | |
template <typename T> class Remote; | |
/** | |
* WeakHolder: | |
* This class contains the object's reference | |
*/ | |
template <typename T> class WeakHolder { | |
int index; | |
Repository<T>* origin; | |
bool created; | |
WeakReference<T>* remote; //Object notified | |
public: | |
WeakHolder(int pos, Repository<int>* master) : | |
index{pos}, origin{master}, created{false} | |
{} | |
std::unique_ptr<Remote<T>> create(T value); | |
void decreaseIndex() { --index; } | |
bool launchUpdateToHolder(int first, int second); //calls holderHasUpdated | |
void setReference(WeakReference<T>* ptr) { if (!remote) remote = ptr; } //set the remote reference once | |
void remoteHasBeenDestroyed(); | |
}; | |
/** | |
* WeakReference: | |
* This class contains the the remote object's state handler | |
*/ | |
template <typename T> class WeakReference { | |
WeakHolder<T>* master; | |
Remote<T>* up; | |
public: | |
WeakReference(WeakHolder<T>* origin, Remote<T>* object) : master{origin}, up{object} {}; | |
~WeakReference() { master->remoteHasBeenDestroyed(); } | |
bool holderHasUpdated(T first, int second); | |
}; | |
/** | |
* Remote: | |
* Objects created by Repository. WARNING: Non copy-able | |
*/ | |
template <typename T> class Remote { | |
std::unique_ptr<WeakReference<T>> remotelylocal{nullptr}; | |
T value; | |
public: | |
Remote(T val) : value{val} {}; | |
T getValue() { return value; } | |
void setValue(T val) { value = val; } | |
void setReference(std::unique_ptr<WeakReference<T>> ptr) { if (!remotelylocal) remotelylocal=std::move(ptr); } | |
WeakReference<T>* getReference() { if (!remotelylocal) return nullptr; return remotelylocal.get(); } | |
}; | |
/** | |
* Repository: | |
* Holders' Repository | |
*/ | |
template <typename T> class Repository { | |
std::vector<std::unique_ptr<WeakHolder<T>>> holders; | |
public: | |
Repository() {}; | |
std::unique_ptr<Remote<T>> createNew(T value); | |
int size() {return holders.size(); } | |
void updateObject(int pos, T newvalue) { | |
holders[pos]->launchUpdateToHolder(newvalue,0); | |
} | |
void removeReference(int pos); //Warning: more secure if this is a Repository's lambda | |
}; | |
//Implementation | |
template <typename T> bool WeakHolder<T>::launchUpdateToHolder(int first, int second) { | |
return remote->holderHasUpdated(first,second); | |
} | |
template <typename T> std::unique_ptr<Remote<T>> WeakHolder<T>::create(T value) { | |
std::unique_ptr<Remote<T>> toret{new Remote<T>(value)}; | |
std::unique_ptr<WeakReference<T>> topass{new WeakReference<T>(this,toret.get())}; | |
toret->setReference(std::move(topass)); | |
this->setReference(toret->getReference()); | |
return toret; | |
} | |
template <typename T> void WeakHolder<T>::remoteHasBeenDestroyed() { | |
origin->removeReference(index); | |
} | |
template <typename T> bool WeakReference<T>::holderHasUpdated(T first, int second) { | |
up->setValue(first); | |
return true; | |
} | |
template <typename T> std::unique_ptr<Remote<T>> Repository<T>::createNew(T value) { | |
holders.emplace(holders.end(),new WeakHolder<T>(holders.size(),this)); | |
return holders[holders.size()-1]->create(value); | |
} | |
template <typename T> void Repository<T>::removeReference(int pos) { | |
holders.erase(holders.begin()+pos); | |
for (int i=pos; i<holders.size(); i++) | |
holders[i]->decreaseIndex(); | |
} | |
/** EXAMPLE */ | |
int main(void) { | |
Repository<int> bordello; | |
std::unique_ptr<Remote<int>> snd = repo.createNew(2); | |
std::unique_ptr<Remote<int>> hrd = repo.createNew(3); | |
{ | |
std::unique_ptr<Remote<int>> fst = repo.createNew(1); | |
bordello.updateObject(2,55); | |
std::cout << fst->getValue() << std::endl; | |
//fst is now destroyed | |
} | |
std::cout << "Size: " << repo.size() << std::endl; //fst holder is hence removed | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment