Praktische Verwendung der Strategievorlage

Die Verwendung von Vorlagen (oder Mustern) in der objektorientierten Programmierung beruht auf dem Wunsch, den Code einfacher und zuverlässiger zu machen und das Rad nicht neu zu erfinden sowie die gemeinsame Arbeit von Programmierern mit unterschiedlichen Schulungsstufen effektiv zu organisieren, um ihnen eine einzige Grundlage für das Verständnis des Quellcodes im konzeptionellen Rahmen der Geschäftslogik zu bieten Anwendungen. Dies bedeutet, dass das Erlernen von Designmustern ein wichtiger Schritt in der beruflichen Entwicklung eines Programmierers ist.

Wie studiere ich Designmuster? Es gibt zwei Ansätze: langweilig und verständlich (Gefällt dir meine Klassifizierung?). Ein langweiliger Ansatz beinhaltet das akademische Studium einer Liste von Mustern anhand abstrakter Beispiele. Persönlich bevorzuge ich das Gegenteil - ein verständlicher Ansatz, wenn Sie die Aufgabe auf einen relativ hohen Formulierungsgrad einstellen, können Sie Entwurfsmuster auswählen. Sie können zwar beide Ansätze kombinieren.

So lass uns gehen?

Die Strategievorlage bezieht sich auf eine Gruppe von Verhaltensvorlagen.

Kurze Definition der Strategievorlage


Die Vorlage dient zum Umschalten zwischen einer Familie von Algorithmen, wenn ein Objekt sein Verhalten aufgrund einer Änderung seines internen Zustands ändert.

Praktische Beispiele für die Anwendung der Strategievorlage


  • Sortieren: Wir möchten diese Zahlen sortieren, wissen jedoch nicht, ob wir BrickSort, BubbleSort oder eine andere Sortierung verwenden werden. Sie haben beispielsweise eine Website, auf der auf einer Seite Elemente angezeigt werden, die auf der Beliebtheit basieren. Viele Dinge können jedoch „beliebt“ sein (die meisten Ansichten, die meisten Abonnenten, das Erstellungsdatum, die meisten Aktivitäten, die wenigsten Kommentare). Falls das Management noch nicht genau weiß, wie eine Bestellung aufzugeben ist, und zu einem späteren Zeitpunkt mit verschiedenen Bestellungen experimentieren möchte, erstellen Sie eine Schnittstelle (IOrderAlgorithm oder etwas anderes) mit der Bestellmethode und ermöglichen dem Orderer-Objekt, die Reihenfolge der konkreten Implementierung der IOrderAlgorithm-Schnittstelle zu delegieren . Sie können CommentOrderer, ActivityOrderer usw. erstellen und diese einfach deaktivieren, wenn neue Anforderungen angezeigt werden.
  • Verarbeiten einer Warteschlange aus heterogenen Objekten (Verarbeiten und Speichern von Daten in der Warteschlange): Ein Beispiel wäre ein Proxysystem, das Objekte aus verschiedenen Datenquellen akkumuliert. Nachdem Sie ein Objekt aus der Warteschlange extrahiert und anschließend gespeichert haben, wird es durch die Auswahlstrategie basierend auf den Eigenschaften dieses Objekts bestimmt.
  • Validierung Wir müssen die Elemente gemäß der „Einige Regel“ überprüfen, aber es ist noch nicht klar, wie diese Regel aussehen wird, und wir können uns neue vorstellen.
  • Authentifizierung: Wählen Sie eine Authentifizierungsstrategie zwischen den Schemata Basic, Digest, OpenID und OAuth aus.

Hier ist ein Beispiel:

interface AuthStrategy {
    auth(): void;
}
class Auth0 implements AuthStrategy {
    auth() {
        log('Authenticating using Auth0 Strategy')
    }
}
class Basic implements AuthStrategy {
    auth() {
        log('Authenticating using Basic Strategy')
    }
}
class OpenID implements AuthStrategy {
    auth() {
        log('Authenticating using OpenID Strategy')
    }
}

class AuthProgram {
    private _strategy: AuthStrategy
    use(strategy: AuthStrategy) {
        this._strategy = strategy
        return this
    }
    authenticate() {
        if(this._strategy == null) {
            log("No Authentication Strategy set.")
        }
        this._strategy.auth()
    }
    route(path: string, strategy: AuthStrategy) {
        this._strategy = strategy
        this.authenticate()
        return this
    }
}

  • (games): — , , , , , , , . , , , , . «», «», «» Attack() . , «», «», «», « » Attack ().
  • (storing information): , , -. , PDF, , . , ; , , A, B C, . PDF , / PDF. , , , , , , B C, , A. , . PDF, , , . . Dependency Injection « / » ( , ), , , , , . , ( , ), , , , . « », «cleanUp» , , , , .
  • (outputting): X , CSV, XML, JSON .
  • (invoicing): - , , - .
  • (navigation): .
  • (logging): Log4Net Log4j , Appenders, Layouts, and Filters.
  • Verschlüsselung: Bei kleinen Dateien können Sie die In-Memory-Strategie verwenden, wenn die gesamte Datei gelesen und im Speicher gespeichert wird (z. B. bei Dateien <1 GB). Bei großen Dateien können Sie eine andere Strategie verwenden, bei der Teile der Datei im Speicher gelesen und teilweise verschlüsselte Ergebnisse in tmp-Dateien gespeichert werden. Dies können zwei verschiedene Strategien für dieselbe Aufgabe sein.

Hier ist ein Beispiel:

//   ""
interface  Cipher  {
     public void performAction();
}

class InMemoryCipherStrategy implements Cipher { 
         public void performAction() {
             //   byte[] ....
         }
}

class SwaptToDiskCipher implements Cipher { 
         public void performAction() {
             //     .... 
         }

}

//   
File file = getFile();
Cipher c = CipherFactory.getCipher( file.size());
c.performAction();

  • Grafikeditor: In der Windows Paint-Anwendung wird beispielsweise eine Strategievorlage implementiert, in der Sie Form und Farbe in verschiedenen Abschnitten unabhängig voneinander auswählen können. Hier sind Form und Farbe Algorithmen, die zur Laufzeit geändert werden können.

Shape redCircle = new RedCircle(); //    «»
Shaped redCircle = new Shape("red","circle"); //   «»

SOLID und Implementierung der Strategievorlage


Was ist das Hauptproblem, das die Vorlage "Strategie" löst? In der Tat ist dies ein Ersatz für den Flatcode IF .... DAS ... ... auf seine Objektimplementierung.

Beispiel für einen schmutzigen Flatcode (falsch):

class Document {...}
class Printer {
    print(doc: Document, printStyle: Number) {
        if(printStyle == 0 /*   */) {
            // ...
        }
        if(printStyle == 1 /*  */) {
            // ...            
        }
        if(printStyle == 2 /*     */) {
            // ...
        }
        if(printStyle == 3 /*     */) {
            // ...            
        }
        if(printStyle == 4 /*     */) {
            // ...
        }
        // ...
    }
}

Ein Beispiel für denselben Code mit der Vorlage "Strategie" (korrekt):

class Document {...}
interface PrintingStrategy {
    printStrategy(d: Document): void;
}
class ColorPrintingStrategy implements PrintingStrategy {
    printStrategy(doc: Document) {
        log(" ")
        // ...
    }
}
class InvertedColorPrintingStrategy implements PrintingStrategy {
    printStrategy(doc: Document) {
        log("  ")
        // ...
    }
}
class Printer {
    private printingStrategy: PrintingStrategy
    print(doc: Document) {
        this.printingStrategy.printStrategy(doc)
    }
}

Hier ist ein weiteres Beispiel für die korrekte Implementierung der Strategievorlage basierend auf SOLID.

//  /
interface LockOpenStrategy {
    open();
    lock();
}
//      
class RetinaScannerLockOpenStrategy implements LockOpenStrategy {
    open() {
        //...
    }
    lock() {
        //...
    }
}

//       
class KeypadLockOpenStrategy implements LockOpenStrategy {
    open() {
        if(password != ""){
            log("Entry Denied")
            return
        }
        //...
    }
    lock() {
        //...
    }
}
//        .
abstract class Door {
    public lockOpenStrategy: LockOpenStrategy
}
//   .
class GlassDoor extends Door {}
//    .
class MetalDoor extends Door {}
//       .
class DoorAdapter {
    openDoor(d: Door) {
        d.lockOpenStrategy.open()
    }
}

Unten ist die tatsächliche Codierung der Logik.

var glassDoor = new GlassDoor(); //   
glassDoor.lockOpenStrategy = new RetinaScannerLockOpenStrategy(); //         
var metalDoor = new MetalDoor(); //     
metalDoor.lockOpenStrategy = new KeypadLockOpenStrategy(); //      .
var door1 = new DoorAdapter().openDoor(glassDoor); //    . 
var door2  = new DoorAdapter().openDoor(metalDoor); //    . 

Wie Sie oben sehen können, handelt es sich um einen vollständig objektorientierten Code, der den prozeduralen Stil IF ... ausschließt . SONST ....... oder SCHALTER ... FALL ...

Warum haben wir übrigens die Adapterklasse verwendet? Die Tür selbst öffnet sich nicht, sie öffnet sich immer mit etwas auf der einen Seite, und auf der anderen Seite können einige Ereignisse vor dem Öffnen der Tür oder nach Abschluss des Öffnens auftreten, z. B. können BeforeOpen () und AfterOpen () ebenfalls verknüpft werden Adapter.

Refactoring und Strategievorlage


Die Strategievorlage sollte verwendet werden, wenn Sie sich wiederholende Algorithmen bemerken, jedoch in unterschiedlichen Variationen. Daher ist es notwendig, die Algorithmen in Klassen zu unterteilen und sie nach Bedarf in Ihrem Programm zu füllen.

Wenn Sie außerdem doppelte bedingte Anweisungen um einen Geschwisteralgorithmus herum bemerken.
Wenn die meisten Klassen Verhalten zugeordnet haben. Und dann müssen Sie es auswählen und in separate Klassen verschieben.

Ich hoffe, diese Auswahl von Beispielen hilft Ihnen, die Vorlage "Strategie" angemessen zu verwenden.
Ich würde mich freuen, wenn Sie in den Kommentaren weitere Beispiele für diese Vorlage nennen können.

Viel Spaß beim Codieren, Freunde und Kollegen!

Source: https://habr.com/ru/post/undefined/


All Articles