I have a collection of related classes, call them
class Manager {
private:
std::vector<Setting> m_settings;
}
class Setting {
private:
std::vector<Action> m_actions;
}
class Action {
private:
Keybind m_keybind;
}
class Keybind {
public:
UpdateKeybind;
private:
TYPE keybind;
}
As you can see from the pseudo-C++ code, Settings have actions, and actions have exactly one key binding. Now, as a user of my application you want to update the Keybind potentially, yes?
I currently have buttons in a keybind-type dialog associated with each action, so the action can handle updating it's own keybind.
My Problem:
How do I ensure that the Keybinding isn't bound to another object?
Possible solutions:
Move UpdateKeybind itself to the Manager class, then have Manager query all the settings.
Have a parent pointer in Action/Setting/Keybind so the Action can query the manager for updated keybind.
Have the Action query other Actions (not great conceptually as far as I can tell).
What I need from you:
What is the most rigorous approach, in terms of maintainability, speed, ease of understanding, and OOP appropriateness, to implementing checking if a Keybind is already found, whether out of my suggested solutions or something else entirely. I have already tried number 1 -- it works, but I feel like it could be better, ya dig?
I was unable to find similar questions on StackOverflow, but if you do I'd love to see them!
Any other pro tips, things to improve are helpful.
Just like #Amardeep says, you can try creating a class managing the mapping between actions and keybindings. Following is an example. It will automatically remove the keybind to the action if the there is new binding to that keybind.
class Manager {
private:
std::vector<Setting*> m_settings;
KeybindPool *m_keybindPool;
};
class Setting {
private:
std::vector<Action*> m_actions;
};
class Action {
public:
void Bind(Keybind* keybind) {
m_manager->m_keybindPool->Update(this, keybind)
}
Keybind* getKeybind() const {
return m_manager->m_keybindPool->getKeybind(this);
}
private:
Manager *m_manager;
};
class KeybindPool {
public:
void Update(Action* action, Keybind* keybind) {
if (m_keybindActionMap.find(keybind) != m_keybindActionMap.end()) {
m_actionKeybindMap.erase(action);
}
m_keybindActionMap[keybind] = action;
m_actionKeybindMap[action] = keybind;
}
Keybind* getKeybind(Action* action) {
return m_actionKeybindMap[action];
}
private:
map<Keybind*, Action*> m_keybindActionMap;
map<Action*, Keybind*> m_actionKeybindMap;
};
class Keybind {
private:
TYPE keybind;
}
Since you have an exactly 1:1 relationship between key bindings and actions, you could start with a pool of key binding objects and draw down from the pool as you configure actions. So when offering up available keys for configuration, any keys already bound would not be in the available pool.
Related
I'm sorry if I don't know the right word for what I'm trying to accomplish.
Basically I have an event handler object which only has a single member. The member is a Stage object.
When the event handler receives an event, I want it to simply use the stage object to call the relevant method. For example:
Event event; //this event is not part of my code, but rather the library I'm using.
Stage s; // my custom class object
EventHandler event_handler; //also my custom class object
event_handler.stage = &s;
if(event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
So what I'm trying to accomplish is that, there will be seperate scopes that my program goes into over time, and I want each scope to have access to the event_handler such that they can do something like:
void some_other_scope(EventHandler* eh) {
Stage* some_new_stage = new Stage(...);
eh->stage = some_new_stage;
}
This way, the original event code stays the same, and the event handler will be calling handle_shutdown on a different object than it was originally going to.
So what I want to do is to overload the handle_shutdown method so that there can be different implementations of it. I know how basic overloading works, it can be done by specifying different parameters, but is there any way to have different definitions of the same class method based on the file that the object was created in?
I was hoping to have several files, each with their own some_other_scope() function, and each file can redefine the handle_shutdown method to do different things based on what that file needs.
I'm sure there's a way to do what I want, I just don't know the right words to use.
It seems you want to use polymorphism:
class IStage
{
public:
virtual ~IStage() = default;
virtual void handle_shutdown() = 0;
// ...
};
class Stage1 : public IStage
{
public:
void handle_shutdown() override { /*Implementation1*/ }
// ...
};
class Stage2 : public IStage
{
public:
void handle_shutdown() override { /*Implementation1*/ }
// ...
};
And then
struct EventHandler
{
std::unique_ptr<IStage> stage;
// ...
};
EventHandler event_handler;
event_handler.stage = std::make_unique<Stage1>();
if (event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
// Later
event_handler.stage = std::make_unique<Stage2>();
if (event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
I have a code similar to the following:
template<class ObjType>
class jsonable
{
private:
static map<string, jsonElem> config;
protected:
virtual void setConfig() = 0;
//other fields and methods in public/private
}
class user : public jsonable<user>
{
protected:
virtual void setConfig();
//other fields and methods in public/private
}
class client : user
{
protected:
virtual void setConfig() {user::setConfig(); /* more config */}
//other fields and methods in public/private
}
The main idea of this code is to save in static variables data related to the class referenced in the template. The problem comes when I want to inherit from the user class: the static variable is shared between user and client classes, instead of one static variable for each class.
I've tried to do something like:
class client : user, jsonable<client>
But a bunch of problems appeared (many methods with same name, and some other related to inherit 2 times the same class). I don't know if there is an elegant way of do this, or even if there is a way at all. (I'm a bit newbie in c++)
Any idea would be welcome! :). And of course, I can "copy" all the contents of user into client but... I would like to do not do that until there are no more options.
Edit:
In order to add context and details to the question, I'm going to explain a bit what I'm doing (or want to do).
Jsonable is a class that provides the ability to serialize into Json another class (helped by https://github.com/nlohmann/json).
To achive this, it uses a static map to store each jsonable-field name and its info (type and position relative to the start of the class in memory, so it can be serialized and deserialized).
The problem comes if a class inherits from another class that inherits from jsonable. Both shares that map, so only the baseclass data is consider when serializing/deserializing. Hope this explanation helps to understand...
Edit2: Giving a full code in a question seems very overkilling to me. If someone wants something to compile, I've uploaded a git repo: https://github.com/HandBe/jsontests
Really thanks to all the people who have put interest on this question!.
A possible solution can be derive client from both user (because it is a user) and jsonable<client> as (private/public apart)
class user : public jsonable<user>
{
protected:
virtual void setConfig();
//other fields and methods in public/private
};
class client: public user, public jsonable<client>
{
virtual void setConfig()
{
user::setConfig();
// more config, referred to jsonable<client>::map
}
}
because it has to implement jsonable for itself (regardless of user).
This is the so-called "stacked parallelogram" inhertiance pattern very common in multiple interface implementations as modular behavior.
Now user and client have each their own configuration
If I understand your problem correctly: you want client to be a user, but also have all the per-class statics defined in jsonable?
Have you considered composition over inheritance? This could work either way:
1) make user a component of client
class client : public jsonable<client>
{
user parent; // could also be a pointer
void setConfig() {parent.setConfig(); /* more config */}
/* ... */
}
2) make jsonable a component:
class user
{
jsonable<user> userjson; // public, private, whatever is appropriate for your design
/* ... */
}
class client : public user
{
jsonable<client> clientjson;
/* ... */
}
I've looked around but couldn't find what I'm looking for (not sure what keywords to use). I'm working on a C++ project myself. This project has windows, pages and fields. A window can contain one or more pages, and a page can contain one or more fields. What's shared across the window, page and field is they have an InputManager which takes care of all the IO of the user. The InputManager can act on the window, the page and the field (for example, some inputs act directly on the page, while some act on the field). Also, a field can generate status messages to be displayed at a location of the containing window.
Right now I have the following structure, but it doesn't seem optimal. There's a lot of pointer passing down, and I'm wondering if there's a better way to do so.
class InputManager
{
//do stuff to return input
}
class StatusManager
{
//do stuff to display statuses
}
class Field
{
friend class Page;
protected:
InputManager *input_manager;
StatusManager *status_manager;
/*
other methods that do stuff that
may recieve from input_manager and
send statuses through the status_manager
*/
}
class Page
{
friend class Window;
protected:
vector<Field* > fields;
InputManager *input_manager;
StatusManager *status_manager;
public:
AddField(Field *field)
{
field->input_manager = this->input_manager;
field->status_manager = this->status_manager;
}
}
class Window
{
protected:
vector<Page *> pages;
InputManager *input_manager;
StatusManager *status_manager;
public:
Window()
{
input_manager = new InputManager();
status_manager = new StatusManager();
}
AddPage(Page *page)
{
page->input_manager = this->input_manager;
page->status_manager = this->status_manager;
}
}
If I want to learn more about these types of problem, what keywords or fields should I be looking into?
I have the following bit of code in my Windows 8 Store app:
public static void ConvertUpdateStreamToCollection<T>(this IObservable<UpdateInfo<T>> input, ObservableCollection<T> list)
{
input
.ObserveOnDispatcher()
.Subscribe(upInfo => UpdateList(upInfo, list));
}
That ObserveOnDispatcher is there b.c. this will often be called on a background thread, and when it updates the observable list I will need it to be on the UI dispatcher. To first order this looks like it works fine when I run the app.
But I wish to test this with unit tests. I'm using the built in MSTest. The ObserveOnDispatcher throws, however, complaining there is no valid Window from which to get a CoreDispatcher.
I've seen work arounds for WPF in other places in Stack overflow. But that looks like just something to make the dispatcher run. This error seems more fundamental. Is there a known workaround?
(edit: better formatting now that I have a keyboard instead of a phone)
There's another way to achieve the same functionality:
.ObserveOnDispatcher()
Is fairly equivalent to:
.ObserveOn(new DispatcherScheduler(Dispatcher.CurrentDispatcher))
Now, instead of that DispatcherScheduler, have a class like:
public static class Schedulers
{
public static IScheduler Dispatcher {get; internal set;}
}
And change usage to:
.ObserveOn(Schedulers.Dispatcher)
Example:
void Main()
{
// For normal usage, we'll set this to the proper DispatcherScheduler
Schedulers.Dispatcher = new DispatcherScheduler(Dispatcher.CurrentDispatcher);
// Do stuff
new Thingy().DoStuff();
// for testing usage, we'll set this to be the immediate scheduler
Schedulers.Dispatcher = Scheduler.Immediate;
// Do stuff
new Thingy().DoStuff();
}
public class Thingy
{
public void DoStuff()
{
var query = Observable.Range(0, 10).ObserveOn(Schedulers.Dispatcher);
query.Subscribe(Console.WriteLine);
}
}
Firstly, can anyone explain how a state object can be shared when the state object has no instance variables ?
This text is taken from GOF, page 308, item 3 (consequences section):
The state object can be shared.
If state objects have no instance variabkes - that is, the state they
represent is encoded entirely in their
type - then contexts can share a
state object. When states are shared in
this way, they are essentially
flyweight.
Can anyone explain this text ?
Secondly, what are the approaches to the state transition decision? I mean the decision of which next state to propagate?
Please help.
Thanks.
In the state pattern you have an represent the state of an object by using state-objects. These state-objects represent a certain state, but they do not have any mutable state of their own. This means they never change. Therefore, any number of objects can use the same state-object at the same time (even from different threads). If the state-object had mutable state, other objects would have to worry about their state-object being changed from elsewhere.
The using of one object instance by many others can be seen as an instance of the flyweight-pattern.
As for the second part of your question, here is an example:
class SomeStateMachine;
class AbstractState {
// abstract baseclass for all state-classes
void input(const std::string & data, SomeStateMachine & caller) = 0;
}
class FinalState : public AbstractState {
FinalState * getInstance(); // always returns same instance
}
class InitialState : public AbstractState {
public:
InitialState * getInstance(); // always returns same instance
void input(const std::string & data, SomeStateMachine & caller) {
std::cout << data << std::endl;
caller.m_State = FinalState::getInstance();
}
}
class SomeStateMachine {
public:
SomeStateMachine() : m_State(InitialState::getInstance())
void input(const std::string & data) {
m_State->input(data, *this);
}
private:
friend class InitialState;
AbstractState * m_State;
};
So you basically pass a reference to the calling object to every method of your state-object. This way, the state-object is able to change the state of the caller when needed. This example might not be very beautiful, but I hope you get the idea.
The paragraph is basically saying that you encode your states as individual classes - then the instance type is the "state" and the classes don't need any instance variables because their type encodes all the information you need.
E.g say I want to have three states "Open", "Active" and "Closed". I might define the following classes:
abstract class State {};
class Open extends State {
public Open() {}
}
class Active extends State {
public Active() {}
}
class Closed extends State {
public Closed() {}
}
--
Another option - I'd suspect this is the combination with flyweight being hinted at in the GOF text would be to create a state class which a bunch of static members (one for each state) which can then be shared -
public class State {
private string name;
private State(String name) {
this.name = name;
}
public final static State OPEN = new State("Open");
public final static State ACTIVE = new State("Active");
public final static State CLOSED = new State("Closed");
}
I had to go digging to remind myself of how all this stuff worked in detail. Kerievsky has a good description of this (I've heavily borrowed from one of his examples above!) and how the state transitions can be handled by sub-classing from the state class, to create classes that manage each transition. See "Refactoring to Patterns" (ISBN: 0321213351)
EDIT(2): His web site has a class diagram for his example - http://www.industriallogic.com/xp/refactoring/alteringConditionalsWithState.html