Sign in to follow this  
Whiles

Generic Platform Interface Design

Recommended Posts

Hi all! :) I'd like to show you a little piece of source code I have written to develop the general cross platform design of my engine. I have designed a central abstract class "Platform" which would work as a sort of api - specific interface for the various classes of the engine. All the os-dependant functions should be implemented in this "Platform" class. I think this method could handle the porting of the engine easily ( I should only write a new platform class to port the code to the various operating systems / consoles ). I would like to read some critics and suggestions because I don't know if it's good design :D
#include <iostream>

class Window;

// Simple interface to the set of classes which abstract the system functions.

class Platform
{
	public:

		virtual Window* CreateWindow () = 0;

		virtual void SetPosition( unsigned int x, unsigned int y, Window* window ) = 0;
};

// Generic window class.

class Window
{
	public:

		Window( Platform* platform )
		{
			m_Platform = platform;
		}

		virtual void SetPosition( unsigned int x, unsigned int y )
		{
			m_Platform->SetPosition( x, y, this );
		}

	protected:
	private:

		Platform*		m_Platform;

		unsigned int	m_Width, m_Height;
		unsigned int	m_X, m_Y;

		bool			m_FullScreen;
};

// Platform Windows implementation.

class WindowsPlatform : public Platform
{
	friend class Window;

	public:

		Window* CreateWindow()
		{
			return new Window( this );
		}

	private:

		void SetPosition( unsigned int x, unsigned int y, Window* window )
		{
			using namespace std;

			cout << "SetPosition()" << endl;
		}
};

It should be used in this way ( of course I'll write a typedef for the platform class in some ifdefs ):
int main()
{
	Platform* platform	= new WindowsPlatform();

	Window* window		= platform->CreateWindow();

	window->SetPosition( 0, 0 );

	return 0;
}

Thank you in advance! Bye:) [Edited by - Whiles on July 26, 2008 11:13:09 AM]

Share this post


Link to post
Share on other sites
My only tip is that you probably don't want to put data members into your generic classes, even if you know beyond a shadow of a doubt that the sub-classes are going to use those members, because you don't know.

In the case of a window, whatever implementation of a window that a given platform uses may already contain position information. In that case, having the data member is likely to be redundant, and will definitely impose on the flexibility of the interface implementations. Have your interfaces totally abstract. (edit: forgot to mention that if you want to change these members, all the application code will have to be recompiled, even though they're protected)

Delving further into the murky depths of opinion, SetPosition should not be a method of Platform. That's just weird, and doesn't make much sense. Even if the implementation of SetPosition uses 'platform' calls instead of 'window' calls, it should still be a method of Window.

Share this post


Link to post
Share on other sites
Thank you for the suggestions!!
So.. Do you suggest to create simple classes such as WindowWin32, WindowLinux, etc ? I was looking for a way to develop the platform specific classes around an interface or something similar to not change the code in lots of parts, but if you think it's not a good design I'll avoid this method...

Share this post


Link to post
Share on other sites
Quote:
Original post by Whiles
Thank you for the suggestions!!
So.. Do you suggest to create simple classes such as WindowWin32, WindowLinux, etc ? I was looking for a way to develop the platform specific classes around an interface or something similar to not change the code in lots of parts, but if you think it's not a good design I'll avoid this method...


Uh, yeah, isn't that what you're already doing? Here's what I'm thinking:

enun WINDOW_TYPE{/*stuff*/};

class IWindow;

class IPlatform{
public:
virtual IWindow* CreateWindow(int, int, int, int, WINDOW_TYPE) = 0;
//and so on, all pure-virtual
};

class IWindow{
public:
virtual int get_ypos() = 0;
virtual int get_xpos() = 0;
virtual int get_width() = 0;
virtual int get_height() = 0;
virtual void setPosition(int, int) = 0;
//functions for binding menus, suchlike
//again, all abstract
};


The I* naming convention just indicates that the classes are pure interface. Notice there are no protected members. Now an implementation, very pseudo because I have no clue about windowing :D.


class Win32Window;

class WindowsPlatform: public IPlatform{
IWindow* CreateWindow(int x, int y, int w, int w, WINDOW_TYPE type){
return (IWindow*) new Win32Window(x, y, w, h, type);//don't inline this
}
//notice how the return is still the interface type, but actually a real class is returned
//same for all other funcs
}

class Win32Window: public IWindow{
Win32Window(int, int, int, int, WINDOW_TYPE);
int get_xpos();
int get_ypos();
int get_width();
int get_height();
void setPosition(int, int);
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this