Design Pattern for separating a model from its graphical representation

1.2k views Asked by At

The Problem

I am looking for (hopefully) a design pattern I might be ignorant of that can help be accomplish some code-separation for the problem I've defined below:

I have a set of classes that represent various entities such as Point, Vector, Arc, etc., that belong on a 2D Cartesian plane, represented by a class Model. The Model class acts as a collection for these entities as well as storing useful calculated values.

I also have a visual interface that should render a 2D image of the state of the model, and can also interact with the model to a small degree by adding entities to the model (for instance, the user can add a Point to the model by clicking on the GUI somewhere.).

First Idea

At first, I had an interface Drawable that had one method, Draw, that would accept a graphics context object, and the implementing entity would draw itself to that context using the graphics libraries I am using (Java Swing/AWT in this case).

This worked well in that the GUI portion of my application simply had to loop through all of the entities in my model and run their Draw method to generate the visualization. The big problem was that I was marrying my model to its graphical representation, and I feel like this bad practice.

Second Idea

I created a EntityDrawer class that would accept an entity, choose a correct drawing method based on the type of entity, then draw to my graphics context.

This approach accomplished the code-separation I was looking for, but the EntityDrawer class relied heavily on an instanceOf/isA approach to determine how to draw the entity, which I have repeatedly seen described as poor design. I tried redesigning this so that class used overloaded methods to determine which drawing method to use, but I realized that this was basically the same instanceOf/isA approach written in a nicer looking way. Also, for every new entity class that I add, I would need to mirror that in this EntityDrawer's code, which feels like a form of coupling to me.


I would like to have as much decoupling between my model and its graphical representation as possible, so that the model can focus on modeling a problem and not on how to render itself to a graphics context. Furthermore, it is likely that I will be adding more model entity types in the future that will have drastically different drawing needs.

So, is there a pattern or design technique I can use to accomplish this? I feel like the two solutions I came up with are sub optimal and that there is probably a design pattern out there that can take care of exactly this kind of problem.

4

There are 4 answers

3
Zifendale On BEST ANSWER

It seems to me that you're missing the Controller part of a Model, View, Controller(Or MVC) design pattern.

The controller will communicate with the model and communicate with the view(your graphics portion) which allows your view and model to be independent of each other.

Here is some additional related reading for the subject: http://www.oracle.com/technetwork/articles/javase/index-142890.html

2
Oscar On
0
Lee Meador On

In the olden days, we used to build all these on top of a drawing abstraction layer with a very simple interface: put a point of color c at point x,y.

Then we wrote drawing classes for each type of object that were based on the low level API.

So there was a Point class that held a PointDrawer that it used when someone called its 'draw()' method. The PointDrawer knew about the Point internals to the extent that it could get the color, x and y and called the low level API to place the point on the display or the paper or to chisel it out of the granite block.

Then there was a Line calls that had a color and two x,y endpoints. The corresponding LineDrawer knew the internals of the Line object and could either create Point objects and tell them to draw themselves or it could call the low level API. This choice lay with the implementer. An alternative was that a new low level method could be added to the API to draw a line. So that made three choices, at three different levels, of how the LineDrawer would work to get the image up on the display.

For each new drawable object, Circle, Arc, Ellipse, Box, FilledBox, etc, there was a corresponding XxxDrawer held inside that did the drawing using some combination of the three levels.

Note that some displays had built in capability to draw arcs and some didn't. This made the choice a device dependent one so there would be a group of 'drawer' subclasses, usually, that would do it. So instead of a LineDrawer there might be a XyzSystems4453DeviceLineDrawer class, amoung others.

This is very confusing but it does allow drawing each thing to have maximum performance (useful if doing animation and you need 24 images per second times however 1000 many arcs there are in the image) plus it makes it pretty easy to add another device thats just like an existing one "except for ...". (You subclass and override the changed stuff, perhaps calling the overriden methods at times.) And if you keep your naming and packaging organized, you can keep the code organized as it grows.

This is all important given that we still, even with the increaed speed available in processors and graphics co-processors, can't draw all the details we need, in the time we have, without being very careful.

0
inor On

I think your goal of separating the model objects from their drawers is important. I would create a separate hierarchy for drawers which can evolve independently of the model. So i would have a PointDrawer and a CircleDrawer etc' (perhaps all extending from some abstract EntityDrawer. PointDrawer may be the base of a whole hierarchy of classes that know how to draw a point in various ways (different colors or on different graphical contexts). The controller should obtain the model objects and the appropriate drawer. You can use Factories... The controller transforms the user actions/requests into model actions/queries/logic (e.g. moving) and then engage in the appropriate drawer