Singleton Patern

Hi guys, I was given assignment which I'll post below. I'm having problems doing it because every website i read is too difficult to understand for me because my english isn't very great.


"You are requested to create a class called robot. Only one instance of the class can exist at a time in case an evil robot tried to reproduce to overtake mankind(you should use the singleton pattern here). The robot should have a private members for a serial number and a name which should be set when initialized using a constructor.
The robot can speak using a speak function which essentially prints some words to the screen. robots have 3 types of speaking_behavior. those with evil behavior say something bad. those with good behavior say something nice. those with mute behavior say nothing at all. Inside the speak function robots with evil behavior should also attempt to create another instance of a robot with evil behavior. you should use the strategy pattern to implement speaking behavior. demonstrate the use of your robot class in the driver function."


I tried to understand how this works for hours but I'm getting nowhere. Any help would be much appreciated.

Thanks.
Take a look at Cubbi's response in the following post for a simple example of a singleton class.
http://www.cplusplus.com/forum/general/60509/
The assignment makes Cubbi's approach a little tricky: A) Eyore91 needs to pass values through a constructor. B) Robot's need to be able to attempt to instantiate another Robot ( it probably shouldn't be a compile error ).

The assignment makes me wonder what level class you are taking. Do you know about exceptions, inheritance and static class variables ( because that is the way I would do it ).?

Edit: In fact, I don't think Cubbi's approach would work at all here. That approach instantiates one Robot for the life of the program. Eyore91 needs to be able to has his one robot go out of scope so that he could potentially instantiate a new one with different serial, name, and behavior.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <string>

class Robot;

class BehaviourInterface {  // Stragegy Pattern
	private:
		Robot* robot;
	public:
		BehaviourInterface (Robot* thisRobot): robot (thisRobot) {}
		virtual void speak() = 0;
		void selfDestruct();
};

class GoodBehaviour: public BehaviourInterface {
	public:
		virtual void speak() override {std::cout << "You look very nice today." << std::endl;}
};

class EvilBehaviour: public BehaviourInterface {
	public:
		EvilBehaviour (Robot* thisRobot): BehaviourInterface (thisRobot) {}
		virtual inline void speak() override;
};

class MuteBehaviour: public BehaviourInterface {
	public:
		virtual void speak() override {}  // nothing said
};

class Robot {
	private:
		int serialNumber;
		std::string name;
		BehaviourInterface* behaviour;
		Robot (int num, const std::string& newName): serialNumber (num), name (newName), behaviour (nullptr) {}
		Robot (const Robot& other);
		const Robot& operator = (const Robot& other);
	public:
		~Robot() {std::cout << name << " destroyed." << std::endl;}
		static Robot* Instance (int serialNumber, const std::string& name) {  // Singleton
			static Robot instance (serialNumber, name);
			return &instance;
		}
		void setBehaviour (BehaviourInterface* newBehaviour) {
			behaviour = newBehaviour;
		}
		void speak() const {behaviour->speak();}
};


void BehaviourInterface::selfDestruct() {
	delete robot;
}

inline void EvilBehaviour::speak() {
	std::cout << "Today you shall die!" << std::endl;
	selfDestruct();
	Robot* newRobot = Robot::Instance (99999, "New Mr. Roboto");
	newRobot->setBehaviour (new EvilBehaviour (newRobot));
}

int main() {
	Robot* robot = Robot::Instance (12345, "Mr. Roboto");
	robot->setBehaviour (new EvilBehaviour (robot));
	robot->speak();
	
	std::cin.get();
}
Last edited on
Sorry, but it won't let me delete my previous post. The line static Robot instance (serialNumber, name); prevents creating a new Robot because static is only called once. Normally we use static for Singleton pattern, but for this particular case, try dropping the static keyword to be able to create a new robot after the previous is destroyed:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <string>
#include <cstdlib>

class Robot;

class BehaviourInterface {  // Stragegy Pattern
	protected:
		Robot* robot;
	public:
		BehaviourInterface (Robot* thisRobot): robot (thisRobot) {}
		virtual void speak() = 0;
		void selfDestruct();
};

class GoodBehaviour: public BehaviourInterface {
	public:
		using BehaviourInterface::BehaviourInterface;
		virtual void speak() override {std::cout << "You look very nice today." << std::endl;}
};

class EvilBehaviour: public BehaviourInterface {
	public:
		using BehaviourInterface::BehaviourInterface;
		virtual inline void speak() override;
};

class MuteBehaviour: public BehaviourInterface {
	public:
		using BehaviourInterface::BehaviourInterface;
		virtual void speak() override {}
};

class Robot {
	private:
		int serialNumber;
		std::string name;
		BehaviourInterface* behaviour;
		static int numRobots;
		Robot (int num, const std::string& newName): serialNumber (num), name (newName), behaviour (nullptr) {
			std::cout << "Robot #" << serialNumber << " " << name << " created." << std::endl;
			numRobots++;
		}
		Robot (const Robot& other);
		const Robot& operator = (const Robot& other);
	public:
		~Robot() {
			std::cout << name << " destroyed." << std::endl;
			numRobots--;
		}
		std::string Name() const {return name;}
		static Robot* Instance (int serialNumber, const std::string& name) {  // Singleton
			if (numRobots == 0)
			{
				Robot* instance = new Robot (serialNumber, name);
				return instance;
			}
			std::cout << "Robot already exists.  Cannot create another until it is destroyed!" << std::endl;
			std::cin.get();
			std::exit(0);
		}
		void setBehaviour (BehaviourInterface* newBehaviour) {
			behaviour = newBehaviour;
			std::cout << "Behaviour of " << name << " established." << std::endl;
		}
		void speak() const {behaviour->speak();}
};
int Robot::numRobots = 0;

void BehaviourInterface::selfDestruct() {
	delete robot;
}

inline void EvilBehaviour::speak() {
	std::cout << robot->Name() << " speaks: Today you shall die!" << std::endl;
	selfDestruct();  // without this, the next robot cannot be created
	Robot* newRobot = Robot::Instance (99999, "New Mr. Roboto");
		newRobot->setBehaviour (new EvilBehaviour (newRobot));
}

int main() {
	Robot* robot = Robot::Instance (12345, "Mr. Roboto");
	robot->setBehaviour (new EvilBehaviour (robot));
	robot->speak();
	std::cin.get();
}

Ouput:
1
2
3
4
5
6
Robot #12345 Mr. Roboto created.
Behaviour of Mr. Roboto established.
Mr. Roboto speaks: Today you shall die!
Mr. Roboto destroyed.
Robot #99999 New Mr. Roboto created.
Behaviour of New Mr. Roboto established.


Output with 'selfDestruct();' commented out:
1
2
3
4
Robot #12345 Mr. Roboto created.
Behaviour of Mr. Roboto established.
Mr. Roboto speaks: Today you shall die!
Robot already exists.  Cannot create another until it is destroyed!
Last edited on
Topic archived. No new replies allowed.