2010-09-30 11 views
9

PHP und .Net haben Verschlüsse; Ich habe mich gefragt, was Beispiele für die Verwendung von Verschlüssen in OOP und Entwurfsmustern sind und welche Vorteile sie gegenüber der reinen OOP-Programmierung haben.Was sind Verwendungen von Verschlüssen für OOP?

Zur Klarstellung, dies ist keine OOP vs. funktionale Programmierung, aber wie man am besten Verschlüsse in einem OOP-Design verwendet. Wie passen Verschlüsse in Fabriken oder das Beobachtermuster? Welche Tricks können Sie ziehen, die das Design verdeutlichen und zum Beispiel zu lockerer Kopplung führen?

+1

Dies sollte wahrscheinlich Community-Wiki sein. – notJim

+0

Ich habe das gleiche gefragt. Diese Seite: http://php.net/manual/en/functions.anonymous.php hat ein Beispiel, aber es kann leicht ohne Schließungen umgeschrieben werden. – Galen

Antwort

3

Verschlüsse sind nützlich für die Ereignisbehandlung. Dieses Beispiel ist ein wenig gekünstelt, aber ich denke, es ist die Idee vermittelt: entweder

class FileOpener 
{ 
    public FileOpener(OpenFileTrigger trigger) 
    { 
     trigger.FileOpenTriggered += (sender, args) => { this.Open(args.PathToFile); }; 
    } 

    public void Open(string pathToFile) 
    { 
     //… 
    } 
} 

meine Datei Opener eine Datei direkt durch den Aufruf instance.Open(pathToFile) öffnen, oder es kann durch ein Ereignis ausgelöst werden. Wenn ich keine anonymen Funktionen und Schließungen hätte, müsste ich eine Methode schreiben, die keinen anderen Zweck hat, als auf dieses Ereignis zu reagieren.

2

Angenommen, Sie möchten eine Klasse mit der Möglichkeit bereitstellen, eine beliebige Anzahl von FileOpener Instanzen zu erstellen, aber den IoC-Prinzipien folgend, möchten Sie nicht, dass die Klasse FileOpener s tatsächlich weiß, wie Sie das tun will nicht new sie). Stattdessen möchten Sie die Abhängigkeitsinjektion verwenden. Sie möchten jedoch nur, dass diese Klasse FileOpener Instanzen generieren kann und nicht irgendeine Instanz. Hier sind, was Sie tun können:

Jetzt haben Sie Ihre Klasse, die FileOpener-Instanzen erstellen müssen. Sie können Dependency Injection verwenden Sie es mit dieser Fähigkeit zur Verfügung zu stellen, während lose Kopplung

class DependsOnFileOpener() 
{ 
    public DependesOnFileOpener(Func<FileOpener> getFileOpener) 
    { 
     // this class can create FileOpener instances any time it wants, without knowing where they come from 
     FileOpener f = getFileOpener(); 
    } 
} 
3
Halte

Jede Sprache, die Verschlüsse hat sie für trampolining verwenden, die eine Technik zur Refactoring Rekursion in Iteration ist. Dies kann Sie aus "Stack Overflow" -Problemen befreien, auf die naive Implementierungen vieler Algorithmen stoßen.

Ein Trampolin ist eine Funktion, die einen Verschluss zurück zum Aufrufer "springt". Die Schließung erfasst "den Rest der Arbeit".

Zum Beispiel in Python Sie einen rekursiven Akkumulator definieren können die Werte in einem Array zusammenfassen:

testdata = range(0, 1000) 
def accum(items): 
     if len(items) == 0: 
       return 0 
     elif len(items) == 1: 
       return items[0] 
     else: 
       return items[0] + accum(items[1:]) 

print "will blow up:", accum(testdata) 

Auf meinem Rechner scheißt dies mit einem Stack-Überlauf, wenn die Länge der Elemente überschreitet 998.

die gleiche Funktion kann in einem Trampolin-Stil mit Schließungen erfolgen:

def accum2(items): 
     bounced = trampoline(items, 0) 
     while (callable(bounced)): 
       bounced = bounced() 
     return bounced 

def trampoline(items, initval): 
     if len(items) == 0: 
       return initval 
     else: 
       return lambda: trampoline(items[1:], initval+items[0]) 

Durch Rekursion Umstellung auf Iteration, Sie den Stapel nicht ausblasen. Der Abschluss hat die Eigenschaft, den Status der Berechnung in sich selbst zu erfassen, anstatt auf dem Stapel wie bei der Rekursion.

+0

Ordentlicher Trick! Ich glaube nicht, dass ich das jemals zuvor gesehen habe. Ist es am häufigsten mit Python (das würde erklären, warum ich das nie gesehen habe)? – FrustratedWithFormsDesigner

+0

Es ist ziemlich häufig in der Lisp-Welt. In den meisten Lisp-Implementierungen wird dies vom Compiler automatisch erledigt ("Tail-Call-Optimierung").Aber manchmal müssen Sie es von Hand tun, weil der Compiler das Muster nur in bestimmten Konfigurationen erkennen kann. –

+0

Ich bin nicht * das * in Imperativsprachen üblich, aber z.B. LEPL (http://www.acooke.org/lepl/) verwendet Trampolining, um zu verhindern, dass komplexe rekursive Abstiegs-Parser den Stapel überfluten. – delnan

Verwandte Themen