The most common design patterns for graphic tasks are Decorator (often with a โfreeโ interface ), Prototype / Clone, and Visitor. It will be useful.
Decorator : if you want to gradually add attributes to the object. For instance:
final int radius = 100; // With fluent interface final Graphic boxedShadedCircle = new Circle(radius, 100, 100).shaded().boxed(); // Without fluent interface final Graphic nonFLuentBoxedShadedCircle = new Boxed(new Shaded(new Circle(radius, 100, 100)));
Prototype / Clone : so that you can duplicate any object (copy / paste functions). This is basically a Clonable interface.
Visitor : if you want to add functionality to objects without adding code to the actual object. Say if your application is some kind of script. See this post for an example: Visitor Template
Now, to talk about your specific solutions:
Decorator seems to be a good way to implement your first solution. Alternative Template method or some composition ("combine a common graphic box with a data object").
For your second solution, Factory seems appropriate.
I canโt say which is better. It depends on your local circumstances. All implementations have pros and cons, and the trick is to choose the one where the pros outweigh the cons.
Updates for the updated question:
ChartBuilder: This is probably the "Builder" design template . This dp is a representation or provision of an abstract description / product, such as a document description or a dataset in different ways.
Director: This is a project of patter Mediator . Or Facade , depending on the intention. Facade, if you "hide" a ball of shitty outdated code, "Mediator", if you coordinate the interaction of several more modern classes. There is a lot of gray area. If the director also interacts with the graphical interface (resize, hide, etc.), he is definitely an intermediary.
In general, your structure is a model / viewer / controller. The director acts as a controller, statistics acts as a model, chartBuilder acts as a viewer.
It is not uncommon that several design patterns overlap, as with a controller as an intermediary.
You can be happier if you implement all this as a request / response, using the Observer design template to respond, and not as direct calls with return values. This is more flexible, and you can hide the latency / calculation / database search in the stream better.
You can use Composite for chartBuilder. If you want to display several types of data at the same time, not just one.