2011-03-21 11 views
1

私がしている:不器嫌な継承の代わりにフィルタ/構成パターン?

class ServiceObject { 

    ServiceClass svcClass; 

    void execute(String operation, Map arguments, ...) { 
     svcClass.execute(this, operation, arguments, ...); 
    } 

} 

その後、私は同期して追加することのサブクラスを持っている:

class SynchronizedServiceObject extends ServiceObject { 

    void execute(String operation, Map arguments, ...) { 
     synchronized(lock) { 
      super.execute(operation, arguments, ...); 
     } 
    } 

} 

私はまた、しかし

class LogContextServiceObject extends ServiceObject { 

    void execute(String operation, Map arguments, ...) { 
     MDC.set("context", myCtx); 
     super.execute(operation, arguments, ...); 
     MDC.remove("context"); 
    } 

} 

ログコンテキストを追加するためのサブクラスを持っています両方の機能を使用したい場合は、両方の機能を持つ別のサブクラスを作成する必要があります。より多くの機能(ロギング、リクエストの書き換えなど)を追加すれば、必要なすべての組み合わせに対して多くのクラスを書く必要があると想像することができます。

代わりに、ServiceObjectの作成時に、サブクラスを削除して、フィルタまたはコンポーネントオブジェクトのいくつかの並べ替えを渡したいと思います。これに対して推奨されるパターンは何ですか(Java、または一般的に)。

答えて

4

有名なGoFの本では、デコレータ。

ServiceObject serviceObject = 
        new LoggingDecorator(
          new SynchronizedDecorator(
            new ServiceObjectImpl() 
          ) 
        ); 
0

最も簡単な解決策は、ファクトリクラスと列挙子を作成することです:

enum ServiceObjectType { SynchronizedServiceObject ,LogContextServiceObject ,ServiceObject } 
static class ServiceObjectFactory { 
    ServiceObject NewService(ServiceObjectType type) { 
     switch(type) { 
      case ServiceObjectType.SynchronizedServiceObject: return new SynchronizedServiceObject(); 
      case ServiceObjectType.LogContextServiceObject : return new LogContextServiceObject(); 
      case ServiceObjectType.ServiceObject : return new ServiceObject(); 
     } 
    } 
} 

使用法:

ServiceObject blah1 = ServiceObjectFactory.NewService(ServiceObjectType.SynchronizedServiceObject); 
ServiceObject blah2 = ServiceObjectFactory.NewService(ServiceObjectType.LogContextServiceObject); 
0
好きなようにあなたがそれらを組み合わせることができ、すべての後

public class LoggingDecorator implements ServiceObject { 

    private final ServiceObject decoratee; 

    public LoggingDecorator(ServiceObject decoratee) { 
     this.decoratee = decoratee; 
    } 


    @Override 
    public void execute(String operation, Map<?, ?> arguments) { 
     MDC.set("context", myCtx); 
     try { 
      decoratee.execute(operation, arguments); 
     } finally { 
      MDC.remove("context"); 
     } 
    } 
} 

public class SynchronizedDecorator implements ServiceObject { 

    private final ServiceObject decoratee; 

    private final Object lock = new Object(); 

    public SynchronizedDecorator(ServiceObject decoratee) { 
     this.decoratee = decoratee; 
    } 

    @Override 
    public void execute(String operation, Map<?, ?> arguments) { 
     synchronized (lock) { 
      decoratee.execute(operation, arguments); 
     } 
    } 
} 

非常に多く聞こえる私はChain of Responsibility patternです。これは、ハンドラが責任を負うまでリクエストを伝播するとよく説明されますが、ハンドラがハンドラを「消費」するまで要求を伝播するためにも使用されます。あなたの場合、無条件にすべてのハンドラに伝播したいと思っています。

関連する問題