Delegationsmönster

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 15 januari 2015; kontroller kräver 14 redigeringar .
Delegation
delegation
Beskrivs i Design Patterns Inte

Delegering är ett  grundläggande designmönster där ett objekt externt uttrycker något beteende , men i själva verket överför ansvaret för att utföra detta beteende till ett relaterat objekt. Delegeringsmönstret är den grundläggande abstraktionen på vilken de andra mönstren - sammansättning (även kallad aggregering), mixins och aspekter - implementeras .

Fördelar

Möjligheten att ändra beteendet hos en viss instans av ett objekt istället för att skapa en ny klass genom arv.

Nackdelar

Detta mönster gör det i allmänhet svårt att optimera för hastighet till förmån för förbättrad abstraktionsrenhet.

Tillämplighet

Java

Även om delegering inte stöds av Java-språket, stöds det av många utvecklingsmiljöer [1] .

Exempel

Java

Ett enkelt exempel

I det här Java - exemplet Bhar klassen en stubmetod som skickar metoder till . Klassen låtsas ha klassattribut . foo()bar()ABA

Källtext i java klass A { void foo () { System . ut . println ( "A: metod foo() anropad" ); } void bar () { System . ut . println ( "A: metodbar() anropad" ); } } klass B { // Skapa ett objekt vars metoder kommer att delegera beteende. A a = nytt A (); void foo () { a . foo (); } void bar () { a . bar (); } } public class Main { public static void main ( String [] args ) { B b = new B (); b . foo (); b . bar (); } } Komplext exempel

Med hjälp av gränssnitt kan delegering göras på ett mer flexibelt och typsäkert sätt. I det här exemplet kan klassen Cdelegera till Aantingen B. Klassen Char metoder för att växla mellan klasser Aoch B. Att inkludera redskapsförlängningen förbättrar typsäkerheten eftersom varje klass måste implementera metoderna i gränssnittet. Den största nackdelen är mer kod.

Låt oss ta ett exempel. Anta att du behöver implementera en timer på ett sådant sätt att någon funktion anropas efter en viss tid. Timerprogrammeraren vill ge en funktionstilldelning till användarna i sin klass (andra programmerare).

Källtext i java /** * Gränssnittet beskriver åtgärden som kommer att anropas när * timerhändelsen inträffar. */ interface TimerAction { void onTime (); } class WakeUpAction implementerar TimerAction { @Override public void onTime () { System . ut . println ( "Dags att gå upp!" ); } } class ChickenIsReadyAction implementerar TimerAction { @Override public void onTime () { System . ut . println ( "Kycklingen är klar!" ); } } /** * Timerklass. Under vissa förhållanden anropas TimerAction. */ class Timer { TimerAction action ; /** * En funktion som programmeraren anropar för att ställa in tiden. */ void run () { if ( isTime ()) { action . onTime (); } } /** * Någon funktion som tar hand om allt tidsarbete. Dess * genomförande är inte intressant i detta sammanhang. * * @return */ private boolean isTime () { return true ; } public static void main ( String [] args ) { System . ut . println ( "Ange åtgärdstyp:" ); Scanner scanner = ny skanner ( System . in ); String actionType = skanner . nästa rad (); Timer timer = ny Timer (); if ( actionType . equalsIgnoreCase ( "ställ in väckningstimer" )) { timer . action = new WakeUpAction (); } else if ( actionType . equalsIgnoreCase ( "ställ kycklingtimer" )) { timer . action = new ChickenIsReadyAction (); } timer . köra (); }

C++

Komplext exempel

Det här exemplet är en C++- version av det komplexa Java-exemplet ovan. Eftersom C++ inte har en gränssnittskonstruktion spelar den helt abstrakta klassen samma roll . För- och nackdelarna är i princip desamma som i Java-exemplet.

Källtext i c++ #include <iostream> klass I { offentliga : virtuellt tomrum f () = 0 ; virtuellt tomrum g () = 0 ; }; klass A : offentlig I { offentliga : void f () { std :: cout << "A: anropsmetod f()" << std :: endl ; } void g () { std :: cout << "A: anropsmetod g()" << std :: endl ; } }; klass B : offentlig I { offentliga : void f () { std :: cout << "B: anropsmetod f()" << std :: endl ; } void g () { std :: cout << "B: anropsmetod g()" << std :: endl ; } }; klass C : public I { offentliga : // Konstruktör C () : m_i ( nytt A () ) { } // Destructor virtual ~ C () { ta bort m_i ; } void f () { m_i -> f (); } void g () { m_i -> g (); } // Med dessa metoder ändrar vi fältobjektet, vars metoder vi kommer att delegera void till A () { ta bort m_i ; m_i = newA ( ); } void toB () { ta bort m_i ; m_i = nytt B (); } privat : // Vi deklarerar ett objekt vars metoder vi kommer att delegera I * m_i ; }; int main () { Cc ; _ c . f (); c . g (); c . toB (); c . f (); c . g (); returnera 0 ; } /* Utdata: A: anropa f()-metoden A: anropa g() -metoden B: anropa f()-metoden B: anropa g()-metoden */

C#

Källtext i C# namespace Patterns { interface I { void f (); voidg ( ); } klass A : I { public void f () { System . Konsol . WriteLine ( "A: anropar f()-metoden" ); } public void g () { System . Konsol . WriteLine ( "A: anropar g()-metoden" ); } } klass B : I { public void f () { System . Konsol . WriteLine ( "B: anropar f()-metoden" ); } public void g () { System . Konsol . WriteLine ( "B: anropar g()" ); } } class C : I { // Skapa ett objekt vars metoder vi kommer att delegera I i = new A (); offentligt tomrum f () { i . f (); } public void g () { i . g (); } // Med dessa metoder ändrar vi fältobjektet, vars metoder vi kommer att delegera public void tillA () { i = new A (); } public void toB () { i = new B (); } } class DelegatePattern { static void Main ( string [] args ) { C c = new C (); c . f (); c . g (); c . toB (); c . f (); c . g (); System . Konsol . ReadKey (); } } } Icke-trivialt exempel

Detta är ett exempel på ett fall som ofta uppstår i praktiken. Det finns en uppgift att skapa en klass för lagring av listan över anställda. Varje anställds data lagras i ett objekt av klassen Employee. Det finns en färdig och standardklass för att lagra en lista med Employee-objekt. Den har redan implementerat mekanismer för att arbeta med listan (till exempel minnesallokering, lägga till och ta bort från listan). Att ärva personallistklassen från objektlistklassen är inte acceptabelt här, eftersom vi kommer att få alla metoder (även de som vi inte är intresserade av). Dessutom kommer vi att behöva utföra typgjutning i vissa fall. Den mest eleganta vägen ut ur det här fallet är att delegera några av metoderna för objektlistklassen till klassen medarbetarlista. I OOP-regler är det bäst att representera listan över objekt med en privat (privat) metod för listan över anställda. I det här fallet kan listan nås via en indexerare.

Källtext i C# använder System ; använder System.Collections.Generic ; använder System.Linq ; använder System.Text ; namnområde Anställda { /// <sammanfattning> /// Klass för att lagra anställds data. /// </summary> class Employee { private string name ; privat stråkavdelning ; _ public Employee ( strängnamn , strängavdelning ) { detta . _ _ namn = namn ; detta . avdelning = avdelning ; } /// <sammanfattning> /// Anställds namn. /// </summary> offentlig sträng Namn { get { returnera detta . namn ; } } /// <sammanfattning> /// Arbetsavdelning. /// </summary> public string Department { get { return this . avdelning ; } } } /// <sammanfattning> /// Klass för att lagra en lista över anställda. /// </summary> class EmployeesList { privat lista < Anställd > anställda = ny lista < Anställd >(); /// <sammanfattning> /// Egenskap för att få och skriva en anställd efter index. /// </summary> /// <param name="index">Anställd index.</param> /// <returns>Anställd.</returns> offentlig Anställd detta [ int index ] { get { return anställda [ index ]; } set { anställda [ index ] = värde ; } } /// <sammanfattning> /// Lägga till en ny anställd. /// </summary> /// <param name="employee">Ny anställd.</param> public void Lägg till ( Anställd anställd ) { anställda . Lägg till ( anställd ); } /// <sammanfattning> /// Ta bort en befintlig anställd. /// </summary> /// <param name="employee">Den anställde som ska tas bort.</param> public void Ta bort ( Anställd anställd ) { anställda . Ta bort ( anställd ); } /// <sammanfattning> /// Sök efter en anställd efter namn. /// </summary> /// <param name="name">Anställds namn.</param> /// <param name="offset">Position att börja söka från.</param> // / < returns>Anställd index.</returns> public int GetIndexOfEmployeeByName ( strängnamn , int offset = 0 ) { for ( int i = offset ; i < anställda . Antal ; i ++) { if ( anställda [ i ] . Namn == namn ) { return i ; } } return - 1 ; } } class Program { static void Main ( string [] args ) { //Skapa en lista över anställda och lägg till poster till den EmployeesList empList = new EmployeesList (); empList . Lägg till ( ny anställd ( "Shlensky Dmitry" , "webstudio" )); empList . Lägg till ( ny anställd ( "Kusy Nazar" , "webstudio" )); empList . Lägg till ( ny anställd ( "Magpie Orest" , "webstudio" )); //Sök efter anställd Kusyi Nazar och visa resultatet när du söker från början och från konsolen på andra plats . WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" ). ToString ()); Konsol . WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" , 2 ). ToString ()); //Sök och ta bort medarbetare Soroka Orestes empList . Remove ( empList [ empList . GetIndexOfEmployeeByName ( "Magpie Orestes" )]); } } } Källtext i C# 2 använder System ; använder System.Collections.Generic ; använder System.Linq ; använder System.Text ; namnområde Anställda { /// <sammanfattning> /// Klass för att lagra anställds data. /// </summary> class Employee { private string name ; privat stråkavdelning ; _ public Employee ( strängnamn , strängavdelning ) { detta . _ _ namn = namn ; detta . avdelning = avdelning ; } /// <sammanfattning> /// Anställds namn. /// </summary> offentlig sträng Namn { get { returnera detta . namn ; } } /// <sammanfattning> /// Arbetsavdelning. /// </summary> public string Department { get { return this . avdelning ; } } } /// <sammanfattning> /// Klass för att lagra en lista över anställda. /// </summary> class EmployeesList { privat lista < Anställd > anställda = ny lista < Anställd >(); /// <sammanfattning> /// Egenskap för att få och skriva en anställd efter index. /// </summary> /// <param name="index">Anställd index.</param> /// <returns>Anställd.</returns> offentlig Anställd detta [ int index ] { get { return anställda [ index ]; } set { anställda [ index ] = värde ; } } /// <sammanfattning> /// Egenskap för att få och skriva en anställd vid namn. /// </summary> /// <param name="name">Anställds namn.</param> /// <returns>Den första anställde vars namn matchade eller null</returns> offentligt Anställd denna [ strängnamn ] { get { foreach ( Anställd artikel i anställda ) { if ( artikel . Namn == namn ) returnera föremål ; } returnera null ; } } /// <sammanfattning> /// Lägga till en ny anställd. /// </summary> /// <param name="employee">Ny anställd.</param> public void Lägg till ( Anställd anställd ) { anställda . Lägg till ( anställd ); } /// <sammanfattning> /// Ta bort en befintlig anställd. /// </summary> /// <param name="employee">Den anställde som ska tas bort.</param> public void Ta bort ( Anställd anställd ) { anställda . Ta bort ( anställd ); } /// <sammanfattning> /// Sök efter en anställd efter namn. /// </summary> /// <param name="name">Anställds namn.</param> /// <param name="offset">Position att börja söka från.</param> // / < returns>Anställd index.</returns > public int GetIndexOfEmployeeByName ( strängnamn , int offset ) { int index = - 1 ; for ( int i = offset ; i < anställda . Antal ; i ++) { if ( anställda [ i ]. Namn == namn ) { index = i ; bryta ; } } returnera index ; } /// <sammanfattning> /// Sök efter en anställd efter namn. /// </summary> /// <param name="name">Anställds namn.</param> /// <returns>Anställd index.</returns> public int GetIndexOfEmployeeByName ( strängnamn ) { return GetIndexOfEmployeeByName ( namn 0 ) ; } } class Program { static void Main ( string [] args ) { //Skapa en lista över anställda och lägg till poster till den EmployeesList empList = new EmployeesList (); empList . Lägg till ( ny anställd ( "Shlensky Dmitry" , "webstudio" )); empList . Lägg till ( ny anställd ( "Kusy Nazar" , "webstudio" )); empList . Lägg till ( ny anställd ( "Magpie Orest" , "webstudio" )); //Sök efter anställd Kusyi Nazar och visa resultatet när du söker från början och från konsolen på andra plats . WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" ). ToString ()); Konsol . WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" , 2 ). ToString ()); //Sök och ta bort medarbetare Soroka Orestes empList . Remove ( empList [ "Magpie Orestes" ]); } } }

Objective-C 2.0

Ett enkelt exempel Objective-C källkod enum { GLEngineChangeView }; @interface GLEngine  : NSObject { id _delegate ; BOOL_event [ NUM ] ; } - ( id ) delegat ; - ( void ) setDelegate: ( id ) delegate ; - ( void ) changeView: ( GLView * ) view ; @slutet @protocol GLEngineDelegate < NSObject > @frivillig - ( BOOL ) motor : ( GLEngine * ) Engine changeView : ( GLView * ) view ; @slutet @interface GLEngine (internt) - ( ogiltig ) registerDelegate ; @slutet @implementationGLEngine _ - ( id ) delegate { returnera _delegate ; } - ( void ) setDelegate: ( id ) delegate { _delegate = delegat ; [ självregistreraDelegat ] ; } - ( void ) changeView: ( GLView * ) view { if ( _event [ GLEngineChangeView ]) { // delegeringsbegäran if ([ _delegate engine : self changeView : view ]) { // använd modifierad vy } annan // begäran behandlades inte } // eller använd standardsättet } - ( void ) registerDelegate { if ([ _delegate responseToSelector : @selector ( motor : changeView :)]) { _event [ GLEngineChangeView ] = JA ; } } @slutet @interface MyGLEngineDelegate  : NSObject < GLEngineDelegate > { // } @slutet @implementationMyGLEngineDelegate _ - ( BOOL ) motor: ( Engine * ) Engine changeView: ( GLView * ) view { // ändra vy } @slutet

ObjectPascal

Ett enkelt exempel Källtext i Object Pascal typ IDelegateInterface = gränssnittsprocedur Metod1 ; _ procedur Metod2 ; slut ; TClassA = klass ( TInterfacedObject , IDelegateInterface ) offentligt förfarande Metod1 ; procedur Metod2 ; slut ; TClassB = klass ( TInterfacedObject , IDelegateInterface ) offentligt förfarande Metod1 ; procedur Metod2 ; slut ; TClassDel = klass ( TInterfacedObject , IDelegateInterface ) privat FInterface : IDelegateInterface ; offentligt förfarande Metod1 ; procedur Metod2 ; procedur ToClassA ; procedur ToClassB ; slut ; genomförande {TClassA} förfarande TClassA . metod1 ; börja Writeln ( 'TClassA.Method1' ) ; slut ; förfarande TClassA . metod2 ; börja Writeln ( 'TClassA.Method2' ) ; slut ; {TClassB} procedur TClassB . metod1 ; börja Writeln ( 'TClassB.Method1' ) ; slut ; procedur TClassB . metod2 ; börja Writeln ( 'TClassB.Method2' ) ; slut ; {TClassDel} procedur TClassDel . metod1 ; börja FInterface . metod1 ; slut ; procedur TClassDel . metod2 ; börja FInterface . metod2 ; slut ; procedur TClassDel . ToClassA ; börja FInterface := TClassA . skapa ; slut ; procedur TClassDel . ToClassB ; börja FGränssnitt := TClassB . skapa ; slut ; Icke-trivialt exempel

Det här exemplet är en Object Pascal -version av det icke-triviala exemplet ovan.

Källtext i Object Pascal enhet EnhetArbetsgivare ; gränssnitt använder Contnrs ; typ // Klass för att lagra anställds data TEmployee = klass privat FName : string ; FDepartament : string ; public constructor Skapa ( namn , avdelning : sträng ) ; publicerad egenskap Namn : sträng läst FName ; egenskap Departament : sträng läst FDepartament ; slut ; // Klass för lagring av listan över anställda TEmployeersList = klass privat // Objekt i klassen "lista över objekt" FEmployeersList : TObjectList ; funktion GetEmployee ( Index : Heltal ) : TEmployee ; procedure SetEmployee ( Index : Heltal ; const Value : TEmployee ) ; offentlig konstruktör Skapa ; förstörare Destroy ; åsidosätta ; function Add ( Anställd : TEmployee ) : Heltal ; procedur Ta bort ( Anställd : TEmployee ) ; function IndexEmployeeByName ( Namn : sträng ; Offset : Heltal = 0 ) : Heltal ; egenskap Anställda [ Index : Heltal ] : TEmployee läs GetEmployee skriv SetEmployee ; standard ; slut ; genomförande {anställd} konstruktör TE-anställd . Skapa ( Namn , Avdelning : sträng ) ; börja FName := Namn ; FDepartament := Avdelning ; slut ; { Temployeers List } konstruktör TEmployeersList . skapa ; begin // Skapa ett objekt vars metoder vi kommer att delegera FEmployeersList := TObjectList . skapa ; slut ; destructor TEmployeersList . Förstöra ; starta FEemployersList . Gratis ; ärvt ; slut ; funktion Temployeers List . GetEmployee ( Index : Heltal ) : TEmployee ; börja Resultat := FEmployeersList [ Index ] som TEmployee ; slut ; procedur TEmployeersList . SetEmployee ( Index : Heltal ; const Value : TEmployee ) ; börja FEmployeersList [ Index ] := Värde ; slut ; funktion Temployeers List . IndexEmployeeByName ( Namn : sträng ; Offset : Heltal = 0 ) : Heltal ; // Sekventiell sökning efter en anställd med namn // Genom argumentet Offset kan du ange från vilken position du ska söka. // Om medarbetaren inte hittas kommer den att returnera ett värde mindre än noll (-1) var Index : Integer ; börja Resultat := - 1 ; // Förutsatt att det inte finns i listan för Index := FEmployeersList . Räkna - 1 ned till Offset gör om ( FEmployeersList [ Index ] som TEmployee ) . Namn = Namn börjar sedan Resultat := Index ; avsluta ; slut ; slut ; funktion Temployeers List . Lägg till ( Anställd : TEmployee ) : Heltal ; börja Resultat := FEemployeers List . Lägg till ( anställd ) ; slut ; procedur TEmployeersList . Ta bort ( Anställd : TEmployee ) ; starta FEemployersList . Ta bort ( anställd ) ; slut ; slut .

Tyvärr använder inte alla programmerare delegeringsmönstret. Till exempel ärvde Borland (utvecklaren av programmeringsmiljön Delphi ) i sitt standardklassbibliotek den tidigare nämnda TObjectList-objektlistklassen från TList - pekarlistklassen . Detta orsakade missnöje bland några erfarna programmerare.

PHP5

Ett enkelt exempel

Det här exemplet är en PHP- version av det enkla Java- exemplet ovan.

PHP5 källkod <?php klass A { public function f () { print "A: Anropa metoden f()<br />" ; } public function g () { print "A: Vi kallar metoden g()<br />" ; } } klass C { privat $_a ; offentlig funktion __construct () { $this -> _a = nytt A ; } public function f () { $this -> _a -> f (); } public function g () { $this -> _a -> g (); } public function y () { print "C: call method y()<br />" ; } } $obj = nytt C ; $obj -> f (); $obj -> g (); $obj -> y (); ?> Komplext exempel

Det här exemplet är en PHP- version av det komplexa Java- exemplet ovan.

PHP5 källkod <?php // använd gränssnitt för typ säkerhetsgränssnitt I { public function f ( ); offentlig funktion g (); } klass A implementerar I { public function f () { print "A: Call f()<br />" ; } public function g () { print "A: Vi kallar metoden g()<br />" ; } } klass B implementerar I { public function f () { print "B: Call f()<br />" ; } public function g () { print "B: Call method g()<br />" ; } } klass C implementerar I { privat $_i ; // skapa ett objekt vars metoder kommer att delegeras offentlig funktion __construct () { $this -> _i = new A ; } // med dessa metoder ändrar vi fältobjektet, vars metoder vi kommer att delegera offentlig funktion till A () { $this -> _i = new A ; } public function toB () { $this -> _i = new B ; } // delegerade metoder public function f () { $this -> _i -> f (); } public function g () { $this -> _i -> g (); } } $obj = nytt C ; $obj -> f (); $obj -> g (); $obj -> toB (); $obj -> f (); $obj -> g (); ?> Icke-trivialt exempel

Det här exemplet är en PHP -version av det icke-triviala exemplet ovan.

PHP5 källkod <?php // klass för lagring av anställd data klass Anställd { privat $_name ; privat $_department ; public function __construct ( $name , $departament ) { $this -> _name = $name ; $this -> _departament = $departament ; } public function getName () { return $this -> _name ; } public function getDepartament () { return $this -> _departament ; } } // klass för att lagra en lista med objekt klass ObjectList { privat $_objList ; public function __construct () { $this -> free (); } /** *för att inte bli uttråkad! */ public function free () { $this -> _objList = array (); } public function count () { return count ( $this -> _objList ); } public function add ( $obj ) { array_push ( $this -> _objList , $obj ); } public function remove ( $obj ) { $k = array_search ( $obj , $this -> _objList , true ); if ( $k !== false ) { unset ( $this -> _objList [ $k ] ); } } public function get ( $index ) { return $this -> _objList [ $index ]; } offentlig funktionsuppsättning ( $index , $obj ) { $ this -> _objList [ $index ] = $obj ; } } // klass för lagring av anställda klass EmployeeList { // objekt av klassen "lista över objekt" privat $_employeersList ; public function __construct (){ // skapa ett objekt vars metoder vi kommer att delegera $this -> _employeersList = new ObjectList ; } public function getEmployer ( $index ) { return $this -> _employeersList -> get ( $index ); } public function setEmployer ( $index , Employee $objEmployer ) { $this -> _employeersList -> set ( $index , $objEmployer ); } public function __destruct () { $this -> _employeersList -> free (); } public function add ( Anställd $objEmployer ) { $this -> _employeersList -> add ( $objEmployer ); } public function remove ( Employee $objEmployer ) { $this -> _employeersList -> remove ( $objEmployer ); } // sekventiell sökning efter en anställd med namn // genom argumentet $offset kan du ställa in från vilken position du ska söka. // om medarbetaren inte hittas kommer den att returnera ett värde mindre än noll (-1) public function getIndexByName ( $name , $offset = 0 ) { $result = - 1 ; // antar att det inte finns i listan $cnt = $this -> _employeersList -> count (); for ( $i = $offset ; $i < $cnt ; $i ++ ) { if ( ! strcmp ( $name , $this -> _employeersList -> get ( $i ) -> getName () ) ) { $result = $i ; bryta ; } } returnera $result ; } } $obj1 = ny anställd ( "Tanasiychuk Stepan" , "webstudio" ); $obj2 = ny anställd ( "Kusy Nazar" , "webstudio" ); $obj3 = ny anställd ( "Magpie Orest" , "webstudio" ); $objList = new EmployeeList (); $objList -> lägg till ( $obj1 ); $objList -> add ( $obj2 ); $objList -> lägg till ( $obj3 ); echo "<pre>" ; print_r ( $objList ); echo "<hr>" ; $index = $objList -> getIndexByName ( "Kusy Nazar" ); $obj4 = $objList -> getEmployer ( $index ); print_r ( $obj4 ); echo "<hr>" ; $objList -> setEmployer ( 2 , $obj4 ); print_r ( $objList ); echo "</pre>" ; ?>

Python

Ett enkelt exempel

Källkod i Python

#coding: utf-8 #python 3 klass A : def f ( self ): print ( 'A : calling method f' ) def g ( self ): print ( 'A : calling method g' ) class C : def __init__ ( själv ): själv . A = A () def f ( själv ): returnera själv . A. _ f () def g ( själv ): returnera själv . A. _ g () c = C () c . f () #A: anropsmetod f c . g () #A: anropsmetod g

JavaScript

Ett enkelt exempel JavaScript-källkod funktion A () { detta . f = function () { alert ( "A: anropar f()-metoden" ); }; detta . g = funktion () { alert ( "A: anropsmetod g()" ); }; } funktion C () { var a = nytt A (); detta . f = funktion () { a . f (); }; detta . g = funktion () { a . g (); }; } var c = nytt C (); c . f (); // "A: anropar metoden f()" c . g (); // "A: anropa g()-metoden" Komplext exempel JavaScript-källkod funktion A () { detta . f = function () { alert ( "A: anropar f()-metoden" ); }; detta . g = funktion () { alert ( "A: anropsmetod g()" ); }; } funktion B () { detta . f = function () { alert ( "B: anropsmetod f()" ); }; detta . g = funktion () { alert ( "B: anropsmetod g()" ); }; } funktion C () { // instansiera A och B en gång var a = nytt A (); varb = nytt B ( ); var cur = a ; // referens till det aktuella objektet med implementering av metoder; standard - A detta . toA = function () { cur = a ; }; detta . toB = function () { cur = b ; }; detta . f = funktion () { cur . f (); }; detta . g = funktion () { cur . g (); }; } var c = nytt C (); c . f (); // "A: anropar metoden f()" c . g (); // "A: anropar g()-metoden" c . toB (); c . f (); // "B: anropar metoden f()" c . g (); // "B: anropar g()-metoden" Icke-trivialt exempel JavaScript-källkod funktion Anställd ( namn , avdelning ) { detta . getName = function () { return name ; }; detta . getDepartament = function () { returnera avdelning ; }; detta . toString = function () { // konvertera till sträng för enkel felsökning returnera "Anställd " + namn + ", " + avdelning ; }; } function EmployeesList () { var anställda = []; detta . add = function () { // function tar ett godtyckligt antal argument för ( var i = 0 , l = argument . length ; i < l ; i ++ ) { if ( arguments [ i ]. constructor == Employee ) { anställda . push ( argument [ i ]); } } }; detta . set = function ( obj , index ) { // typ check if ( obj . constructor == Anställd ) { radera anställda [ index ]; anställda [ index ] = obj ; } }; detta . remove = function ( obj ) { for ( var i = 0 , l = anställda . längd ; i < l ; i ++ ) { if ( anställda [ i ] == obj ) { anställda . skarv ( i , 1 ); jag- ; _ l - ; } } }; detta . getByIndex = function ( num ) { returnera anställda [ num ]; }; detta . getIndexByName = function ( name , offset ) { // sekventiell sökning efter en anställd med namn // genom offset-argumentet kan du ställa in från vilken position du ska söka. (standard 0) // om anställd inte hittas, returnera -1 för ( var i = offset || 0 , l = anställda . längd ; i < l ; i ++ ) { if ( anställda [ i ]. getName () = = namn ) returnera i ; } retur - 1 ; }; detta . toString = function () { // konvertera till sträng för enkel felsökning var ret = "" ; for ( var i = 0 , l = anställda . längd ; i < l ; i ++ ) { ret += i + ": " + anställda [ i ] + "\n" ; } return ret ; }; } var o1 = ny anställd ( "Tanasiychuk Stepan" , "webstudio" ); var o2 = ny anställd ( "Kusy Nazar" , "webbstudio" ); var o3 = ny anställd ( "Magpie Orest" , "webstudio" ); var emps = new EmployeesList (); emps . addera ( o1 , o2 , o3 ); // du kan lägga till en och en varning ( emps ); // "0: Anställd Tanasiychuk Stepan, webbstudio // 1: Anställd Kusyi Nazar, webbstudio // 2: Anställd Soroka Orest, webbstudio" var obj4 = emps . getByIndex ( emps . getIndexByName ( "Kusy Nazar" ) ); // få en länk till anställd varning ( obj4 ); // "Anställd Kusyi Nazar, webbstudio" emps . set ( obj4 , 2 ); // istället för den 2:a (från noll) anställde, infoga obj4 alert ( emps ); // "0: Anställd Tanasiychuk Stepan, webbstudio // 1: Anställd Kusyi Nazar, webbstudio // 2: Anställd Kusyi Nazar, webbstudio" emps . ta bort ( obj4 ); // ta bort anställd obj4 alert ( emps ); // "0: Anställd Tanasiychuk Stepan, webbstudio"

VB.NET

Komplext exempel Källkod i VB.NET Namnutrymmesmönster _ Gränssnitt I Sub f () Sub g ( ) Slutgränssnitt Klass A - redskap I Offentlig Sub f () Implementer I . f System . Konsol . WriteLine ( "A: anropar f()-metoden" ) End Sub Offentligt under g () Genomförande I . g System . Konsol . WriteLine ( "A: anropar g()-metoden" ) End Sub End Class Klass B - redskap I Offentlig Sub f () Implementer I . f System . Konsol . WriteLine ( "B: anropar f()-metoden" ) End Sub Offentligt under g () Genomförande I . g System . Konsol . WriteLine ( "B: anropar g()-metoden" ) End Sub End Class Klass C - redskap I ' Skapa ett objekt vars metoder vi kommer att delegera Privat i As I = New A () Public Sub f () Implementer i . fi . _ f () End Sub Offentlig sub g () Implementer i . g i . g () End Sub ' Med dessa metoder ändrar vi fältobjektet, vars metoder vi kommer att delegera Public Sub tillA () i = New A () End Sub Public Sub toB () i = New B () End Sub End Class Klass Delegatmönster Delad Sub Main () Dim c Som ny C () c . f () c . g () c . tillB () c . f () c . g () System . Konsol . ReadKey () End Sub End Class End Namespace Icke-trivialt exempel Källkod i VB.NET Importsystem.Collections.Generiskt importsystem.Linq Importsystem.Text _ _ _ Namnområde Anställda ''' <sammanfattning> ''' Klass för lagring av personaldata. ''' </summary> Klass Anställd Privat m_name As String Privat m_department As String Public Sub New ( ByVal name As String , ByVal departament As String ) Me . m_name = namnge mig . m_department = avdelning End Sub ''' <sammanfattning> ''' Anställds namn. ''' </summary> Offentlig skrivskyddad egenskapsnamn ( ) Som sträng Get Return Me . m_name End Get End Property ''' <sammanfattning> ''' Arbetsavdelning. ''' </summary> Public ReadOnly Property Department () Som sträng Get Return Me . m_department End Get End Property End Class ''' <sammanfattning> ''' Klass för att lagra en lista över anställda. ''' </summary> Class EmployeesList Privatanställda som ny lista ( Of Anställd ) () ''' <sammanfattning> ''' Egenskap för att få och skriva en anställd efter index. ''' </summary> ''' <param name="index">Anställd index.</param> ''' <returns>Anställd.</returns> Standardobjekt för offentlig egendom ( ByVal index som heltal ) Som anställd Returnera anställda ( index ) End Get Set ( ByVal value As Employee ) anställda ( index ) = värde End Set End Property ''' <sammanfattning> ''' Lägger till en ny anställd. ''' </summary> ''' <param name="employee">Ny anställd.</param> Public Sub Add ( ByVal anställd som anställd ) anställda . Lägg till ( anställd ) End Sub ''' <sammanfattning> ''' Ta bort en befintlig anställd. ''' </summary> ''' <param name="employee">Anställd att ta bort.</param> Public Sub Remove ( ByVal anställd som anställd ) anställda . Ta bort ( anställd ) End Sub ''' <sammanfattning> ''' Sök efter en anställd efter namn. ''' </summary> ''' <param name="name">Anställds namn.</param> ''' <returns>Anställd index.</returns> Offentlig funktion GetIndexOfEmployeeByName ( ByVal name As String ) As Integer Dim index Som heltal = - 1 För i Som heltal = 0 Till anställda . Räkna - 1 Om anställda ( i ). Namn = namn index = i Avsluta För Slut Om Nästa Returnera index Slutfunktion _ ''' <sammanfattning> ''' Sök efter en anställd efter namn. ''' </summary> ''' <param name="name">Anställds namn.</param> ''' <param name="offset">Position att börja söka från.</param> '' ' < returns>Anställd index.</returns> Offentlig funktion GetIndexOfEmployeeByName ( ByVal name As String , ByVal offset As Integer ) As Integer Dim index As Integer = - 1 För i Som heltal = offset Till anställda . Räkna - 1 Om anställda ( i ). Namn = namn index = i Avsluta För Slut Om Nästa Returnera index Slut Funktion Slutklass _ Class Program Shared Sub Main () 'Skapa en lista över anställda och lägg till poster till den Dim empList As New EmployeesList () empList . Lägg till ( Ny anställd ( "Shlensky Dmitry" , "webstudio" )) empList . Lägg till ( Ny anställd ( "Kusy Nazar" , "webstudio" )) empList . Lägg till ( ny anställd ( "Magpie Orest" , "webstudio" ))) 'Söker efter medarbetaren Kusyi Nazar och visar resultatet när du söker från början och från konsolen på andra plats . WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" ). ToString ()) Console . WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" , 2 ). ToString ()) 'Sök och ta bort anställd Soroka Orestes empList . Ta bort ( empList ( empList . GetIndexOfEmployeeByName ( "Magpie Orestes" ))) Console . Läs () End Sub End Class End Namespace

Se även

Anteckningar

  1. Bruce Eckel. Java filosofi. - 4:e upplagan. - LLC Publishing House "Peter", 2016. - S. 215. - 1165 sid.

Litteratur

  • Julian Bucknell "Fundamentala algoritmer och datastrukturer i Delphi". Ed. Diasoft 2003
  • Grand M. Designmönster i Java. 2004
  • Bruce Eckel "Java Philosophy". Ed. "Peter" 2016