Secret Creator [Problem of the Week]
After the Design Patterns course has ended in FCIS, and following up with the wicked problems of my friend, Fouad, I decided to post a code design problem I heard lately …
class Secret
{
// TODO: class body goes here ..
}
class Creator
{
// TODO: class body goes here ..
}
You have two classes: Secret and Creator.
Code both classes such that no other class than Creator is allowed to instantiate a local object of Secret. In other words, I can create an object of Secret as long as this code is inside Creator. If I’m inside any other class than Creator, I can’t!!!
The goal is to restrict the developer writing the code; creating an object of a certain class is restricted to another class, the only class allowed to perform such operation.
Note: The solution should be standard. No using “friend” classes and such keywords. Solve it in C/C++, C# or Java – standard code won’t differ!
As Fouad did, post your answers as comments. Comments will be moderated. Wrong answers will be posted, correct ones won’t
The correct answer will be posted by next Friday, or if I get five correct answers – the earlier!


i have an idea
class Creator
{
private:
class Secret
{
// TODO: class body goes here ..
};
// TODO: class body goes here ..
};
Jaqoup
August 16, 2008 at 6:02 pm
Coding Secret as a private class inside Creator solution doesn’t match the problem definition. Now, class Secret is totally hidden from the whole application, no body said we wanted that. The two classes shall remain separate and publicly accessible.
AlaaShaker
August 16, 2008 at 6:16 pm
class secret
{
public:
virtual void ay7aga()=0;
};
class creator
{
private:
class a: public secret
{
public:
a(){}
virtual void ay7aga()
{
//:)
}
};
public:
secret *getone()
{
return new a();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
creator obj;
secret *s = obj.getone();
s->ay7aga();
return 0;
}
anonymous
August 16, 2008 at 11:19 pm
Sorry Mr.Anonymous, but your code doesn’t prevent me from doing this outside class Creator (as in the _tmain function for instance, or any other new class):
Secret* s = new Secret();Think again …
AlaaShaker
August 16, 2008 at 11:42 pm
your code doesn’t prevent me from doing this outside class Creator (as in the _tmain function for instance, or any other new class):
Secret* s = new Secret();
at least you didn’t try to compile the line of code you argue and if you tried you will get the following error
Error 1 error C2259: ’secret’ : cannot instantiate abstract class
anonymous
August 17, 2008 at 8:03 am
My apologies, I missed the “=0;” part in the virtual function. My bad!
Still your solution isn’t completely right, that’s why I didn’t try compiling it. The rule is: Only Caller can instantiate Secret. I need to restrict the developer from doing elsewise, your code doesn’t!
I could simply create a third class that subclasses Secret and implement the virtual function and then use it anywhere as much as I please (pretty much the same code as class a, but outside Caller). By doing so, I break the restriction, I break the rule.
Give it another try
AlaaShaker
August 17, 2008 at 11:27 am
How about making the constructor of Secret protected and making Creator derive from it?
Technically, any other class can do this but it more or less does the intended goal.
A really big problem with this solution is that it violates the is-a rule of inheritance, because there’s no guarantee that Creator can be used anywhere Secret is used, and creator would inherit a lot of methods it doesn’t need.
Thus my solution is good only as a trick/ puzzle answer and not recommended for practical code
Mohamed Samy
August 17, 2008 at 6:46 pm
First, let me thank you for giving it some time
Well, you said it yourself; any other class can do that.
In this specific case, I’m more concerned about the restricting-the-developer part of the problem.
AlaaShaker
August 17, 2008 at 10:12 pm
An implementation like this would prevent the developer from Creating Secret class from anywhere but Creator.
Class Creator
{
public:
secret* CreateSecretObject() ;
private:
Class Secret
{
}
}
This way the developer won’t be able to access Secret class except by Calling the CreateSecretObject from the Creator class , i guess
!!!
Mahmoud Osama
August 17, 2008 at 11:15 pm
Ok then how about:
class Secret
{
private Secret(){}
public static GiveInstanceTo(Creator c)
{
c._secretInstance = new Secret( );
}
}
class Creator
{
public Secret _secretInstance;
public Secret CreateSecret( )
{
Secret.GiveInstanceTo(this);
return _secretInstance;
}
}
This method is very cumbersome (not to mention non-threadsafe) so again not recommended for real apps.
This method has a ‘hole’ in that I can derive from creator and use the ‘GiveInstanceTo’ on the derived object, or did you mean “Works only inside ‘Creator’ and its subclasses”?
Mohamed Samy
August 18, 2008 at 8:36 pm
what about this /*JAVA*/
public final class Creator
{
public final class secret
{
secret() //default modifier
{
. . .
}
};
blah blah blah ...
};
Jaqoup
August 19, 2008 at 9:57 am
To Mohamed Samy:
Your answer is the CLOSEST!
The only problem with your code is that I could easily trick the code inside any other class using these 3 lines of code:
Creator dummyCreator = new Creator();Secret.GiveInstanceTo(dummyCreator);
Secret myWickedSecret = dummyCreator._secretInstance;
(BTW, there’s no need to return the Secret object in Creator.CreateInstance() .. I meant to use the Secret object locally inside Creator, but it’s OK
)
Your answer, again, is the CLOSEST! You’re almost there, fadellak zalata as they say
AlaaShaker
August 19, 2008 at 12:28 pm
To Abdallah:
I’m sorry again. The keyword “final” will only prevent me from subclassing any of both classes.
It doesn’t mean I can’t do something like:
Creator.Secret s = new Creator.Secret();(I didn’t check the syntax, but you know what I mean)
Try again
AlaaShaker
August 19, 2008 at 12:31 pm
HINTS:
> Don’t go for inheritance. It’s not that way.
> Think of the simplest design pattern, it would help refresh your brain.
> Focus on the task: No instantiation outside Creator. Force the developer!
AlaaShaker
August 19, 2008 at 12:33 pm
ok i know that it only prevents subclassing
what will prevent u from doing
new Creator.Secret();
will be the “default access modifier”ed constructor
which will not be visible except inside the Creator classes and its subclasses ( thats y i used final in Creator)
Jaqoup
August 19, 2008 at 12:42 pm
To Abdallah:
I will have to disagree. It’s wrong
It’s only coz we both used the wrong syntax. I can still do this:
Creator c = new Creator();Creator.Secret s = c.new Secret();
Plus, I don’t want language specific solutions. Zaker Java kowayess ba2a
AlaaShaker
August 19, 2008 at 1:21 pm
I think I got it. Thanks for the hints
This time it should be bullet proof: no external classes, even subclasses of creator, can access the secret!
class Secret
{
private Secret(){}
public static GiveInstanceTo(Creator c)
{
c.SetSecret( new Secret() );
}
}
class Creator
{
private Secret _secretInstance;
public SetSecret(Secret s) { _secretInstance = s;}
public Secret CreateSecret( )
{
Secret.GiveInstanceTo(this);
return _secretInstance;
}
}
Mohamed Samy
August 19, 2008 at 9:51 pm
WE HAVE A WINNER
)
Mohamed Samy is the first to solve it … CONGRATS!
(It’s bullet proof this time
Let’s hope someone else does ..
AlaaShaker
August 19, 2008 at 10:22 pm
ummmmm after thinking a lot to use the Factory method, but failed!!
I thought to modify Mohamed Samy’s code ((as it was the closest
))
>Here is it
class Secret
{
private Secret() { }
public static void GiveInstanceTo(Creator c)
{
c.SecretInstance = new Secret();
}
}
class Creator
{
private static Secret _secretInstance;
public void CreateSecret()
{
if (_secretInstance == null)
Secret.GiveInstanceTo(this);
}
public Secret SecretInstance
{
set
{
if (_secretInstance == null)
_secretInstance = value;
}
}
}
I think its now liable to Singleton Pattern ((which is the Simplest Design Pattern too
:D))…..
Please confirm if thats the Correct Answer
Shady Ahmed El-Yasaki
August 20, 2008 at 11:41 am
WE HAVE A SECOND WINNER
Good thinking Shady, u just revealed Mohamed Samy’s solution
It seems that Mohamed Samy’s solution plus my hints have made it easier … LOL
Even though, I do have a somehow different solution .. will keep it till the end ..
AlaaShaker
August 20, 2008 at 3:43 pm
If you don’t want to do some OO tricks , I see that the most simple solution will be to use a normal key-lock schema , just give the “Creator” some fixed GUID “as you do in com interfaces”
and add to the class “Secret” :
DWORD CreateInstance(GUID callerGuid, any other paramaters )
{
check the GUID if it matches the Creator GUID
{
}
Mohammad Diab
August 20, 2008 at 6:16 pm
Secret should be an internal class inside of Creator with its ctor private,…
That way only creator can use that ctor, so only creator can instantiate secret…
Nice one Alaa ☺
Mustafa
August 20, 2008 at 9:10 pm
To Mustafa:
Thanks, but your solution isn’t quite correct
I believe if you declared the constructor of Secret as private, that won’t allow Creator to instantiate it, even if the first is a nested class in the latter.
I need a coded solution plzzz, that compiles .. standard, and language independant
AlaaShaker
August 20, 2008 at 9:35 pm
ANOTHER THIRD WINNER
Congrats to MAD, your answer is the closest to mine ..
AlaaShaker
August 20, 2008 at 9:36 pm
in C# at least it will
Mustafa
August 22, 2008 at 2:44 am
To Mustafa:
No, it won’t .. try it
AlaaShaker
August 22, 2008 at 6:32 pm
To Mustafa:
No, it won’t .. try it .. you should get:
AlaaShaker
August 22, 2008 at 6:34 pm
[...] Creator SOLVED [Problem of the Week] After a vigorous week of solutions to this hard problem, I will now post my solution [...]
Secret Creator SOLVED [Problem of the Week] « AlaaShaker’s Weblog
August 22, 2008 at 6:47 pm
[...] Easier One [Problem of the week] if you think last week’s problem from Alaa wasn’t that easy. and mine in the week before that was a little [...]
An Easier One [Problem of the week] « more about the 8
August 23, 2008 at 11:30 am