The situation: I have to handle and take action on various commands, which can be encapsulated in the command design pattern. So right now I have
class Command {
virtual void applyCommand(IFoo& foo) = 0;
virtual ~Command() = default;
};
and of course I inherit this interface into my individual command classes.
However now, I realize that just passing IFoo isn't enough. I want to be able to access private data members in my ConcreteFoo class. I justify this break in encapsulation because when it comes down to it, all these objects are basically just helper functions for my ConcreteFoo class. I'm fine with them being strongly coupled because one way or the other, I have to write these methods, and doing the CDP makes it more readable.
So, I change my class to
class Command {
virtual void applyCommand(ConcreteFoo& foo) = 0;
virtual ~Command() = default;
};
and in my ConcreteFoo class I declare
friend class Command;
However, friendship apparently is not inherited into the subclasses of Command, the classes that actually do the work. So I can't actually get access to the data I need.
My current thoughts on solving this are:
1.) Take the L and just handle this without the CDP
- possible, but I don't really want to take this route if I can avoid it
2.) Make data members in ConcreteFoo public
- no
3.) Make data members in ConcreteFoo protected, and somehow make Command a subclass of ConcreteFoo
- no
4.) Manually declare each Command subclass a friend, so like
friend class CommandA;
friend class CommandB;
friend class CommandC;
friend class CommandD;
...
- decent, but might not scale well. on the plus side, if I forget to friend, it should fail at compile time
None of these options are particularly appealing to me. Is there something else I can do?
You’re basically working on visitor pattern (your Command class is a visitor to Foo classes).
One way to go around this, you might have a public interface of Command (
applyCommandnon-virtual) and virtual implementation(s) (applyCommandImplvirtual). You can makeCommanditself a friend andCommand::applyCommandcould extract the necessary data and pass it to the particularapplyCommandImpl.Normally, you’d simply extract the necessary parameters and pass those. However, if you really want to access all members, then you might do this: have the members of Foo in a struct (say,
Foo1DO, as in data object) and inherit from it privately to haveFoo1. Then you can have a simple getter to reachFoo1DOfromFoo1inapplyCommand.