I've used two methods before...
1. Make the UI object an entity. Update it as part of the game loop. Render it using the standard render system of your game. If appropriate, use flags to know when it needs updating. Along the lines you're thinking. This is what I did in Stick Tennis. I wasn't sure it would work when I started, but it turned out rather well. Benefits - you can layer the text within the game scene, you can use the game engine to drive animations and other time based effects in the display.
2. Use an event bus - a shared event dispatcher instance - for the game to communicate changes to the world outside it. Any system in the game can send events down the bus (e.g. eventBus.dispatch( new ScoreEvent( ScoreEvent.CHANGED, score ) ) and objects outside of the game can listen for these events. The code outside the game follows whatever pattern you want to use, so may use the score changed event to update the model, for example, or to draw the new score directly on screen, without maintaining any model. Whatever you wish. Benefits - you can use any UI code architecture independent of Ash.
Richard