tags:

views:

76

answers:

3

I have a toughie I'm trying to wrap my head around. I have some public interfaces and some package-private classes as shown below.

Basically my package private class (called UltraDecoder below) needs some grungy decode logic to decode data and perform some operations on it for its own internal use. However I would also like to make use of that grungy decode logic for other purposes. What I can't seem to do is to figure out a good way to export my grungy decode logic as an interface that can be used by external classes, and also still use it internally to my UltraDecoder class without exposing internal details of UltraDecoder.

Any suggestions?

/** structured metadata */
public interface Metadata { ... }

/**
 * an opaque data item that can be unpackaged
 * to zero or more pairs of (Metadata metadata, int value)
 */ 
public interface DataItem { ... }

public interface SuperDecoder {
   ...
   /** decodes the item and passes each (metadata, value) pair
    *  to a listener by calling its onUpdate() method
    */
   public void decode(DataItem item, SuperDecoderListener listener);
}

public interface SuperDecoderListener {
   public void onUpdate(Metadata m, int value);
}

/* package-private classes implementation classes follow */
class UltraDecoder implements SuperDecoder
{
   static private class SmartObjectWithMetadata
   {
       final private Metadata metadata;
       public Metadata getMetadata();
   }

   private interface UltraDecoderListener
   {
       public void onUpdate(SmartObjectWithMetadata, int value);
   }

   private void ultraDecode(DataItem item, UltraDecoderListener listener)
   {
      /* ... does lots of grungework to obtain 
         the (SmartObjectWithMetadata, value) pairs that correspond to this
         DataItem.

         Calls listener.onUpdate(smartObject, value) zero or more times.
       */          
   }

   public doSomething() 
   { 
      /* ... calls ultraDecode() ... this happens normally */ 
   }
   @Override public void decode(DataItem item, 
       final SuperDecoderListener listener)
   {
      /* ??? how do we leverage ultraDecode ??? 
       * Below, we can do it but we have to create 
       * a new adapter object each time. 
       */
      ultraDecode(item, new UltraDecoderListener() {
         @Override public void onUpdate(
            SmartObjectWithMetadata smartObject,
            int value)
         {
            listener.onUpdate(smartObject.getMetadata(), value);
         }
      }
   }
}
+1  A: 

Create a public class DecoderUtil in the same package as UltraDecoder.

    public class DecoderUtil {
        public static void decode(SuperDecoder decoder) {
           //do common stuff
           if( decoder instanceof UltraDecoder ){
                //do stuff specific to UltraDecoder
           }
        }
    }
singhspk
I don't see how that would work. The interfaces are different.
Jason S
A: 

I have myself a hard time in understanding your functional requirement, but it at least sounds like that you simply need a public abstract class with some "default" logic already implemented which you can then reuse in subclasses. It's called the Template Method Pattern. You see this also practically everywhere in Java Collections and IO API's.

BalusC
A: 

Could you add an overload for onUpdate in UDL that takes an SDL parameter? That being said, I really wouldn't worry about the overhead of object creation unless you know it's a problem.

CurtainDog