Korosh Afshar wrote:
Static singletons and avalon are not a very good match. One could say "Static Singletons are Considered Evil" in the multi-application multi-classloader universe. See

I agree with you. I am trying to move away from using Singletons
all-together.


Part of the problem for me is that I have many classes created in a
hierarchy starting with the Avalon Component that creates the root
class. These classes themselves are not compoments hence don't have
access to Configuration object unless passed in to them. Hence the
convinience of a Singleton that already had all these parameters. I
don't know of a less painfull way of doing this and yet abide by OO best
practices.

for non-components closely tied to the base component already, I usually pass the containing component in inside the constructor:


public interface LifecycleExposingService
{
        Configuration getConfiguration();
        Context getContext();
}

public interface MyService {}

// this is split into many helper classes
public class MyServiceImpl
        implements MyService, LifecycleExposingService { ... }

public class MyServiceHelper
{
        LifecycleExposingService m_service;

        public MyServiceHelper( LifecycleExposingService service )
        {
                m_service = service;
        }

        public Object doHelpfulStuff()
        {
                String someParameter = m_service.getConfiguration()
                        .getChild( "blah" ).getAttribute( "blah" );

                // ...
        }
}

Wouldn't want to call it "best practice" for every situation (if you're making getConfiguration() public you're exposing it to other services as well if the container doesn't do proxying, moreover, you're tying MyServiceHelper to avalon-framework and LifecycleExposingService, which you might not want to do), it can be useful.

An alternative is to use an AbstractServiceHelper something like so:

public abstract class AbstractConfigurable extends AbstractLogEnabled
{
        private Configuration m_configuration;

public AbstractConfigurable() { super(); }

        public configure( Configuration c )
                throws ConfigurationException
        {
                m_configuration = c;
        }

        // final for performance :D
        protected final Configuration getConfiguration()
        {
                return m_configuration;
        }
}

public class AbstractServiceHelper
        extends AbstractConfigurable
{
        public AbstractServiceHelper() { super(); }

        // maybe there's some other stuff here
        // you want to do for all your helpers...
        // basically you're replacing initialization
        // of common static fields here...
}

class SomeMyServiceHelper extends AbstractServiceHelper
{
        public Object doHelpfulStuff()
        {
                String someParameter = getConfiguration()
                        .getChild( "blah" ).getAttribute( "blah" );

                // ...
        }
}

the advantage over the previous approach mentioned being that you don't tie your helper classes to any "LifecycleExposingService" interface, though in this example, SomeMyServiceHelper is still somewhat closely tied to Configuration.

Note your MyServiceImpl becomes a sort of "pseudocontainer". With this setup, you're wanting do something like:

class MyServiceImpl
{
        SomeMyServiceHelper someHelper;
        SomeMyOtherServiceHelper otherHelper;

        MyServiceImpl()
        {
                someHelper = new SomeMyServiceHelper();
                otherHelper = new SomeMyOtherServiceHelper();

                // ...
        }

        enableLogging( Logger logger )
        {
                ContainerUtil.enableLogging( someHelper, logger );
                ContainerUtil.enableLogging( otherHelper, logger );

                // ...
        }
        configure( Configuration c )
        {
                ContainerUtil.configure( someHelper, c );
                ContainerUtil.configure( otherHelper, c );

                // ...
        }

        // ...
}

Also note that while SomeMyServiceHelper can be seen and used as an avalon component, you're not wanting to think about it as such. In the example abouve, SomeMyServiceHelper is referencing the configuration provided for the MyService work interface, rather than the configuration provided for the non-existent SomeMyService work interface. We sometimes call these objects "pseudocomponents", and its helpful to dub them as such in javadoc so other people understand the slightly different implications as well.

Not really "best practices", but an indication of how to merge the Facade pattern with the avalon lifecycle :D. Of course, this doesn't really make migrating a static/singleton setup to a COP setup any less painful!

cheers,

- Leo



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to