On Tue, Jan 7, 2014 at 4:26 PM, John Hendrikx <hj...@xs4all.nl> wrote:
> On 7/01/2014 14:50, Tomas Mikula wrote: > >> Interesting ideas. I'm wondering, do you switch skins often enough that >> you are worried about performance (and thus care about reusability of >> skins)? Because I don't see how reusability of skins saves you lines of >> code - whether the code is in the constructor or in the initialize() >> method, it is there somewhere. In my opinion, reusing objects is more >> complicated than creating fresh instances and the only justification for it >> is performance. >> > > To address your last point first, if you already are required to write a > proper dispose method, then fresh instances should be just as easy/hard to > write as reusable ones. Everything is already in place, just rename the > constructor. Of course, if you did not write a proper dispose method, then > your object will stick around or cause other trouble. With fresh instances > you won't notice this so readily -- in JavaFX for example, the problem of > having objects that are no longer actively reachable through the > SceneGraph, but are still participating in Event handling (because they > registered non-weak listeners) can be a nice source of surprises. With > reusable objects, you'll notice the bugs in your cleanup code likely the > first time you reuse it. > With a non-reusable skin, dispose is pretty much just removing the listeners. With a reusable instance, I suspect there is more work to reset the state of the instance (e.g. removing children, or, if you were concerned about performance, returning them to a pool of objects). So I would argue fresh instances are never more complicated than reusable ones, while the opposite is true only in simple cases. > Anyway, for me, making Skins reusable makes them easier to use with > bindings, My understanding of skins is that they are the view of the MVC pattern and that the rest of the application should not depend on the particular implementation. > and it ofcourse saves creating a factory. I see the "skin" of an object > as the same as say its background color. There is no reason (anymore I > think) that one should be treated so differently from the other. > One outstanding difference is that a skin is stateful, while a background color is stateless (immutable). Thus you can use the same instance of background color for many controls, but you cannot do that with skin instances. In this respect, a skin provider is a better analogy to background color (you can use the same skin provider with many controls). > > private final Skin someExistingSkin = new SkinA(); > private final Skin someExistingSkin2 = new SkinB(); > > void changeToSquareLook() { > myControl.setSkin(someExistingSkin); > } > > void changeToRoundLook() { > myControl.setSkin(someExistingSkin2); > } > > vs. > > private final SkinFactory skinFactory = new SkinFactory() { > public Skin createSkin(Control control) { > return new SkinA(control); > } > }; > > private final SkinFactory skinFactory2 = new SkinFactory() { > public Skin createSkin(Control control) { > return new SkinB(control); > } > }; > > void changeToSquareLook() { > myControl.setSkin(skinFactory.createSkin(myControl)); > } > > void changeToRoundLook() { > myControl.setSkin(skinFactory2.createSkin(myControl)); > } > With lambdas, the skin factories become one-liners, yielding the same total number of lines. > > It's not really about performance, but ease of use. The binding case > requires a ChangeListener instead of just bind(). > > > I agree with you on the problem of separation of skin initialization from >> setSkin(). Another way to address this could be deprecating the original >> setSkin() method and introducing >> >> setSkin(SkinProvider<C> skinProvider); >> >> where SkinProvider is a SAM interface and thus the above method could be >> called like this: >> >> setSkin(control -> new MySkin(control)); >> >> I know this defeats reusability of skins altogether, so you (and others) >> may disagree. >> > Maybe if there was a "skinProviderProperty"... then I could bind to that > atleast. Still introduces lots of factories (or functions). > > --John > > Furthermore, neither the current state nor your proposal prevents you from doing this: Skin<MyControl> skin = new MySkin(); myControl1.setSkin(skin); myControl2.setSkin(skin); My proposal does not allow you to write such code. Best, Tomas