2011-01-14 7 views
2

Ich weiß, dass es eine Aufruffunktion gibt, die das Zeug macht, ich bin insgesamt an der "Korrektheit" der Verwendung eines solchen Verhaltens interessiert. Mein Problem ist das: Ich habe ein Service-Objekt, das Methoden enthält, die ich Dienste betrachte. Was ich tun möchte, ist das Verhalten dieser Dienste ohne späteres Eindringen zu ändern. Zum Beispiel:Kann ich Runtime entschiedene Methodenaufrufe in Java aufrufen?

class MyService { 

     public ServiceResponse ServeMeDonuts() { 
     do stuff... 
     return new ServiceResponse(); 

} 

nach 2 Monaten finde ich heraus, dass ich den gleichen Service zu einem neuen Client-Anwendung, und ich brauche auch einige zusätzliche Dinge zu tun wie Setzen eines Flags, oder zu machen oder zu aktualisieren, bestimmte Daten bieten müssen , oder codieren Sie die Antwort anders. Was ich tun kann, ist Pop-up und werfen einige IFs. Meiner Meinung nach ist das nicht gut, denn es bedeutet Interaktion mit getestetem Code und kann zu unerwünschtem Verhalten für die vorherigen Service-Clients führen.

Also komme ich und füge etwas meiner Registrierung hinzu und sage dem System, dass der "NewClient" ein anderes Verhalten hat. Also werde ich etwas tun:

public interface Behavior { 
    public void preExecute(); 
    public void postExecute(); 
} 

public class BehaviorOfMyService implements Behavior{ 
     String method; 
     String clientType; 

     public void BehaviorOfMyService(String method,String clientType) { 
       this.method = method; 
       this.clientType = clientType; 
     } 

     public void preExecute() { 

     Method preCall = this.getClass().getMethod("pre" + this.method + this.clientType); 
     if(preCall != null) { 
      return preCall.invoke(); 
     } 
      return false; 
     } 

     ...same for postExecute(); 
    public void preServeMeDonutsNewClient() { 
      do the stuff... 
    } 
} 

, wenn das System etwas tun wird, wie diese

if(registrySaysThereIs different behavior set for this ServiceObject) { 
     Class toBeCalled = Class.forName("BehaviorOf" + usedServiceObjectName); 
     Object instance = toBeCalled.getConstructor().newInstance(method,client); 
     instance.preExecute(); 
     ....call the service... 
     instance.postExecute(); 
     .... 
} 

Ich bin nicht besonders interessiert Richtigkeit Code wie in Richtigkeit des Denkens und Ansatz. Eigentlich muss ich das in PHP machen, was ich als eine Art Popmusik des Programmierens sehe, die ich aus kommerziellen Gründen "singen" muss, obwohl ich POP spiele, möchte ich wirklich nach dem Buch singen, so dass ich meine mehr beiseite lege oder weniger inspirierte Analogie Ich möchte wirklich Ihre Meinung zu diesem Thema für seine praktische Notwendigkeit und technischen Ansatz wissen.

Dank

Antwort

1

Nizza Fall Aspect Oriented Programming anzuwenden. Mit AOP können Sie Ereignisse oder Methoden mit aspects verknüpfen, um zusätzliche Logik vor oder nach dem Ereignis zu verarbeiten.

Es gibt gute Beispiele für AOP here und auch Beispiele für Java here

Dieses Beispiel mit aspectwerkz, um Ihren Fall sehr ähnlich ist, ist das Hinzufügen grundsätzlich Post und Pre-Methode Handler um eine Service-Ausführung.

Ich bin nicht wirklich vertraut mit AOP in PHP, aber es gibt einige Projekte, die Sie wie this one.

+1

Eigentlich habe ich zuerst darüber nachgedacht: "Wenn Objekte Aspekte haben können, als dass Dienste Verhalten haben können", frage ich mich nun, warum ich nicht vor der Veröffentlichung noch tiefer ins AOP geschaut habe Rad. Danke für die kurze aber umfassende Antwort. –

0

verwenden können, was Sie brauchen, ist ein Proxy, wobei Sie einige zusätzliche Verhalten unabhängig von dem Objekt definieren proxied werden. ZB:

public class ServiceHandler implements InvocationHandler { 
    private final Object target; 

    public static Object createProxy(Object target) { 
     return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
      target.getClass().getInterfaces(), new ServiceHandler(target)); 
    } 

    public ServiceHandler(Object target) { 
     this.target = target; 
    } 

    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) 
     throws Throwable { 
     // define preexecute behaviour 
     Object result = method.invoke(target, args); 
     // define postexecute behaviour 
     return result; 
    } 
} 

Sie würden dann wie folgt verwenden:

public static void main(String[] args) { 
     Service serviceImpl = new ServiceImpl(); 
     Service service = (Service) ServiceHandler.createProxy(serviceImpl); 
     // use service 
    } 
1

Meiner Meinung nach ist dies nicht gut, wie es bedeutet Interaktion mit getesteten Code und führen in un Verhalten wollte die vorherigen Service-Clients.

Deshalb haben Sie automatisierte Tests. Was Sie wollen, kann mit AOP getan werden, aber wirklich, wirklich sollte nicht, weil es den Code sehr schwer zu pflegen macht (was ein allgemeines Problem von AOP ist und ein Grund, warum es nicht viel gefangen hat).

Es ist nur ein weiteres Beispiel, Code schlechter zu machen, aus Angst, etwas zu zerstören, das funktioniert. Am Ende, jede Änderung kann potenziell Dinge zu brechen, und durch schmerzhafte Verrenkungen zu isolieren die Änderungen aus dem "guten" Code und doch haben sie funktionieren, wird nur in Elend enden.

+0

Sie haben recht mit automatisiertem Testen, aber für einen Fall von Diensten, bei denen Clients andere Anwendungen sind, vielleicht völlig unterschiedliche Anwendungen, die den Dienst erfordern, sind Tests fast unmöglich und einige Zeit kann vergehen, bis jemand herausfindet, dass etwas schief läuft. Ich bin der größte Fan des KISS-Prinzips (halte es einfach dumm), deshalb habe ich viel Zeit zum Nachdenken investiert, bevor ich es "besser" mache. Wie auch immer, ich schätze deine Meinung. Danke –

+0

@Catalin: Deshalb ist es extrem wichtig, dass solche Dienste eine sehr streng und explizit definierte Schnittstelle haben. Dann können Sie eine Testsuite haben, die den Schnittstellenvertrag abdeckt, und wenn ein Client sich auf ein Verhalten verlässt, das nicht durch den Vertrag garantiert ist, ist es sein eigener verdammter Fehler. Natürlich hilft das nicht viel, wenn Sie einen Dienst geerbt haben, der nie einen solchen Vertrag hatte und "organisch" gewachsen ist. –