Future of Skins
Tomas Mikula
tomas.mikula at gmail.com
Tue Jan 7 09:11:43 PST 2014
On Tue, Jan 7, 2014 at 4:26 PM, John Hendrikx <hjohn at 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
More information about the openjfx-dev
mailing list