A well-known and good practice is to avoid subclassing top-level containers (JFrame, JDialog, JInternalFrame).
Regarding JPanel, several practices are in use:
- subclass it for every view (then add
all components inside the subclass
constructor)
- create a ViewBuilder (for each kind
of view) that dynamically adds
components to a "standard"
JPanel
I generally use the first option, which seems more logical to me, but I also sometimes use the second way, with some level of adaptation: my view builder actually creates and stores (as fields) all components but adds them to an existing panel (passed as an argument).
For example, I use that in order to reuse sets of components: e.g. I have an AddressView class that works like that and I add it twice to a ContactView that subclasses JPanel, once for home address, once for office address.
One may say that I could also subclass JPanel for AddressView and then add 2 instances to my ContactView panel. The reason I don't do that is because Swing LayoutManagers don't support alignment of components across different panels, thus the resulting ContactView panel is not visually pleasing in this case.