I recently made a simple Space Invadors game using an 'entity system'. It's a pattern that separates attributes and behaviours extremely well. It took me a few iterations to fully understand it, but once you get a few components designed it becomes extremely simples to compose new objects using your existing components.
You should read this:
It's updated frequently by an extremely knowledgable guy. It's also the only entity system discussion with concrete code examples.
My iterations went as follows:
The first iteration had an "EntitySystem" object which was as Adam describes; however my components still had methods- my 'renderable' component had a paint() method, and my position component had a move() method and etc. When I began to flesh out the entities I realized that I needed to start passing message between components and ordering the execution of components updates....way too messy.
So, I went back and re-read T-machines blog. There is a lot of information in the comment threads- and in them he really emphasizes that components do not have behaviours- behaviours are provided by the entity systems. In this way you do not need to pass messages between components and order component updates because the ordering is determined by the global order of system execution. Ok. Maybe that's too abstract.
Anyway for iteration #2 this is what I gleaned from the blog:
EntityManager - acts as the component "database", which can be queried for entities which contain certain types of components. This can even be backed by an in-memory database for speedy access...see t-machine part 5 for more info.
EntitySystem - Each system is essentially just a method which operates on a set of entites. Each system will use component x,y and z of an entity to get it's work done. So you would query the manager for entities with components x,y and z then pass that result to the system.
Entity - just an id, like a long. The entity is what groups a set of components instances together into an 'entity'.
Component - a set of fields....no behaviours! when you start adding behaviours it starts to get messy...even in a simple Space Invadors game.
Edit: by the way, 'dt' is the delta time since the last main loop invocation
So my main Invadors loop is this:
Collection<Entity> entitiesWithGuns = manager.getEntitiesWith(Gun.class);
Collection<Entity> entitiesWithDamagable =
Collection<Entity> entitiesWithInvadorDamagable = manager.getEntitiesWith(InvadorDamagable.class);
Collection<Entity> entitiesWithInvadorMovement = manager.getEntitiesWith(InvadorMovement.class);
Collection<Entity> entitiesWithVelocity = manager.getEntitiesWith(Velocity.class);
Collection<Entity> entitiesWithPositionAndForm = manager.getEntitiesWith(Position.class, Form.class);
It looks a little weird at first, but it's incredibly flexible. It's also very easy to optimize; for different component types you can have different backing datastores to make retrieval faster. For the 'form' class you can have it backed with a quadtree to speed access for collision detection.
I'm like you; I'm a seasoned developer but had no experience writing games. I spent a some time researching gave dev patterns, and this one caught my eye. It is in no way the only way to do things, but I've found it very intuitive and robust. I believe the pattern was officially discussed in book 6 of the series "Game Programming Gems" - http://www.amazon.com/Game-Programming-Gems/dp/1584500492. I haven't read any of the books myself but I hear they are the de-facto reference for game programming.