Delegation is the basic design pattern in which an object externally expresses some behavior , but in reality transfers responsibility for the implementation of this behavior to the associated object. The delegation template is a fundamental abstraction , on the basis of which other templates are implemented - composition (also called aggregation), impurities (mixins) and aspects (aspects).
| Delegation | |
|---|---|
| Delegation | |
| Described in Design Patterns | Not |
Pros
The ability to change the behavior of a specific instance of an object instead of creating a new class by inheritance.
Cons
This pattern usually makes speed optimization more difficult in favor of improved clarity of abstraction.
Applicability
Java
Although delegation is not supported by the Java language, its support is present in many development environments. [one]
Examples
Java
A simple example
In this Java example, class B has a method stub that passes methods foo() and bar() class A Class B pretends to have class A attributes.
class A {
void foo () {
System out . println ( "A: foo () method called" );
}
void bar () {
System out . println ( "A: method bar ()" called );
}
}
class B {
// Create an object whose methods will be delegated behavior.
A a = new 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 ();
}
}
Complicated Example
Using interfaces , delegation can be implemented more flexibly and with type protection (typesafe). In this example, class C can delegate to either class A or class B Class C has methods for switching between classes A and B Enabling the implements extension improves type safety because each class must execute methods in an interface. The main disadvantage is the large amount of code.
We give an example. Suppose you want to implement a timer so that after a certain amount of time some function is called. The timer programmer wants to provide the task of the function to users of his class (other programmers).
/ **
* The interface describes the action that will be called upon occurrence
* timer events.
* /
interface TimerAction {
void onTime ();
}
class WakeUpAction implements TimerAction {
@Override
public void onTime () {
System out . println ( "Time to get up!" );
}
}
class ChickenIsReadyAction implements TimerAction {
@Override
public void onTime () {
System out . println ( "Chicken is ready!" );
}
}
/ **
* Timer class. Under certain conditions, the TimerAction action is called.
* /
class Timer {
TimerAction action ;
/ **
* The function that the programmer calls to set the time.
* /
void run () {
if ( isTime ()) {
action . onTime ();
}
}
/ **
* Some function that takes on all the work over time. Her
* implementation is not interesting in this context.
*
* @return
* /
private boolean isTime () {
return true ;
}
public static void main ( String [] args ) {
System out . println ( "Enter the type of action:" );
Scanner scanner = new Scanner ( System . In );
String actionType = scanner . nextLine ();
Timer timer = new Timer ();
if ( actionType . equalsIgnoreCase ( "set wake up timer" )) {
timer . action = new WakeUpAction ();
} else if ( actionType . equalsIgnoreCase ( "set chicken timer" )) {
timer . action = new ChickenIsReadyAction ();
}
timer . run ();
}
C ++
Complicated Example
This example is the C ++ version of the sophisticated Java example above. Since C ++ does not have an interface construct, the fully abstract class plays the same role. The advantages and disadvantages are basically the same as in the Java example.
#include <iostream>
class I {
public :
virtual void f () = 0 ;
virtual void g () = 0 ;
};
class A : public I {
public :
void f () { std :: cout << "A: call the f () method << std :: endl ; }
void g () { std :: cout << "A: call the g () method << std :: endl ; }
};
class B : public I {
public :
void f () { std :: cout << "B: we call the f () method << std :: endl ; }
void g () { std :: cout << "B: call the g () method << std :: endl ; }
};
class C : public I {
public :
// Constructor
C () : m_i ( new A () ) { }
// Destructor
virtual ~ C () {
delete m_i ;
}
void f () { m_i -> f (); }
void g () { m_i -> g (); }
// Using these methods, we change the object field whose methods we will delegate
void toA () {
delete m_i ;
m_i = new A ();
}
void toB () {
delete m_i ;
m_i = new B ();
}
private :
// Declare an object whose methods we will delegate
I * m_i ;
};
int main () {
C c ;
c . f ();
c . g ();
c . toB ();
c . f ();
c . g ();
return 0 ;
}
/ * Output:
A: we call the f () method
A: we call the g () method
B: we call the f () method
B: we call the g () method
* /
C #
namespace Patterns
{
interface I
{
void f ();
void g ();
}
class A
: I
{
public void f ()
{
System Console WriteLine ( "A: call the f () method" );
}
public void g ()
{
System Console WriteLine ( "A: we call the g () method" );
}
}
class B
: I
{
public void f ()
{
System Console WriteLine ( "B: we call the f () method" );
}
public void g ()
{
System Console WriteLine ( "B: we call the g () method" );
}
}
class C
: I
{
// Create an object whose methods we will delegate
I i = new A ();
public void f ()
{
i . f ();
}
public void g ()
{
i . g ();
}
// Using these methods, we change the object field whose methods we will delegate
public void toA ()
{
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 Console ReadKey ();
}
}
}
Nontrivial Example
This is an example of a case often encountered in practice. The task is to create a class for storing a list of employees. Each employee data is stored in an object of the Employee class. There is a ready-made and standard class for storing a list of Employee objects. It already implements mechanisms for working with the list (for example, memory allocation, adding and removing from the list). Inheriting the employee list class from the object list class is not acceptable here, because we will get all the methods (even those that are not of interest to us). In addition, in some cases we will have to typecast. The most elegant way out of this case is to delegate to the employee list class part of the methods of the object list class. In the OOP rules, it is best to present the list of objects using the private (private) method of list of employees. In this case, access to the list is possible through the indexer.
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
namespace Employees
{
/// <summary>
/// Class for storing employee data.
/// </summary>
class Employee
{
private string name ;
private string department ;
public Employee ( string name , string departament )
{
this . name = name ;
this . department = departament ;
}
/// <summary>
/// Name of employee.
/// </summary>
public string Name
{
get { return this . name ; }
}
/// <summary>
/// Department of work.
/// </summary>
public string Department
{
get { return this . department ; }
}
}
/// <summary>
/// Class for storing a list of employees.
/// </summary>
class EmployeesList
{
private List < Employee > employees = new List < Employee > ();
/// <summary>
/// Property for getting and writing employee by index.
/// </summary>
/// <param name = "index"> Employee index. </param>
/// <returns> Employee. </returns>
public Employee this [ int index ]
{
get
{
return employees [ index ];
}
set
{
employees [ index ] = value ;
}
}
/// <summary>
/// Add a new employee.
/// </summary>
/// <param name = "employee"> New employee. </param>
public void Add ( Employee employee )
{
employees . Add ( employee );
}
/// <summary>
/// Delete existing employee.
/// </summary>
/// <param name = "employee"> The employee to delete. </param>
public void Remove ( Employee employee )
{
employees . Remove ( employee );
}
/// <summary>
/// Sequential search for an employee by name.
/// </summary>
/// <param name = "name"> Employee name. </param>
/// <param name = "offset"> The position from which to start the search. </param>
/// <returns> Employee Index. </returns>
public int GetIndexOfEmployeeByName ( string name , int offset = 0 )
{
for ( int i = offset ; i < employees . Count ; i ++)
{
if ( employees [ i ]. Name == name )
{
return i ;
}
}
return - 1 ;
}
}
class program
{
static void Main ( string [] args )
{
// Create a list of employees and add entries to it
EmployeesList empList = new EmployeesList ();
empList . Add ( new Employee ( "Shlyonsky Dmitry" , "web studio" ));
empList . Add ( new Employee ( "Kusyy Nazar" , "web studio" ));
empList . Add ( new Employee ( "Magpie Orest" , "web studio" ));
// Search for an employee Kusyy Nazar and display the result when searching from the beginning and from the 2nd position
Console WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" ). ToString ());
Console WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" , 2 ). ToString ());
// Search and delete an employee of Magpie Orest
empList . Remove ( empList [ empList . GetIndexOfEmployeeByName ( "Forty Orest" )]);
}
}
}
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
namespace Employees
{
/// <summary>
/// Class for storing employee data.
/// </summary>
class Employee
{
private string name ;
private string department ;
public Employee ( string name , string departament )
{
this . name = name ;
this . department = departament ;
}
/// <summary>
/// Name of employee.
/// </summary>
public string Name
{
get { return this . name ; }
}
/// <summary>
/// Department of work.
/// </summary>
public string Department
{
get { return this . department ; }
}
}
/// <summary>
/// Class for storing a list of employees.
/// </summary>
class EmployeesList
{
private List < Employee > employees = new List < Employee > ();
/// <summary>
/// Property for getting and writing employee by index.
/// </summary>
/// <param name = "index"> Employee index. </param>
/// <returns> Employee. </returns>
public Employee this [ int index ]
{
get
{
return employees [ index ];
}
set
{
employees [ index ] = value ;
}
}
/// <summary>
/// Property for receiving and recording an employee by name.
/// </summary>
/// <param name = "name"> Employee name. </param>
/// <returns> The first employee to have the same name or null </returns>
public Employee this [ string name ]
{
get
{
foreach ( Employee item in employees ) {
if ( item . Name == name )
return item ;
}
return null ;
}
}
/// <summary>
/// Add a new employee.
/// </summary>
/// <param name = "employee"> New employee. </param>
public void Add ( Employee employee )
{
employees . Add ( employee );
}
/// <summary>
/// Delete existing employee.
/// </summary>
/// <param name = "employee"> The employee to delete. </param>
public void Remove ( Employee employee )
{
employees . Remove ( employee );
}
/// <summary>
/// Sequential search for an employee by name.
/// </summary>
/// <param name = "name"> Employee name. </param>
/// <param name = "offset"> The position from which to start the search. </param>
/// <returns> Employee Index. </returns>
public int GetIndexOfEmployeeByName ( string name , int offset )
{
int index = - 1 ;
for ( int i = offset ; i < employees . Count ; i ++)
{
if ( employees [ i ]. Name == name )
{
index = i ;
break ;
}
}
return index ;
}
/// <summary>
/// Sequential search for an employee by name.
/// </summary>
/// <param name = "name"> Employee name. </param>
/// <returns> Employee Index. </returns>
public int GetIndexOfEmployeeByName ( string name )
{
return GetIndexOfEmployeeByName ( name , 0 );
}
}
class program
{
static void Main ( string [] args )
{
// Create a list of employees and add entries to it
EmployeesList empList = new EmployeesList ();
empList . Add ( new Employee ( "Shlyonsky Dmitry" , "web studio" ));
empList . Add ( new Employee ( "Kusyy Nazar" , "web studio" ));
empList . Add ( new Employee ( "Magpie Orest" , "web studio" ));
// Search for an employee Kusy Nazar and display the result when searching from the beginning and from the 2nd position
Console WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" ). ToString ());
Console WriteLine ( empList . GetIndexOfEmployeeByName ( "Kusy Nazar" , 2 ). ToString ());
// Search and delete an employee of Magpie Orest
empList . Remove ( empList [ "Magpie Orest" ]);
}
}
}
Objective-C 2.0
A simple example
enum {
GLEngineChangeView
};
@interface GLEngine : NSObject {
id _delegate ;
BOOL _event [ NUM ];
}
- ( id ) delegate ;
- ( void ) setDelegate: ( id ) delegate ;
- ( void ) changeView: ( GLView * ) view ;
@end
@protocol GLEngineDelegate < NSObject >
@optional
- ( BOOL ) engine : ( GLEngine * ) engine changeView : ( GLView * ) view ;
@end
@interface GLEngine (Internal)
- ( void ) registerDelegate ;
@end
@implementation GLEngine
- ( id ) delegate {
return _delegate ;
}
- ( void ) setDelegate: ( id ) delegate {
_delegate = delegate ;
[ self registerDelegate ];
}
- ( void ) changeView: ( GLView * ) view {
if ( _event [ GLEngineChangeView ]) {
// delegate the request
if ([ _delegate engine : self changeView : view ]) {
// use the changed view
}
else
// request was not processed
}
// or use the standard method
}
- ( void ) registerDelegate {
if ([ _delegate responseToSelector : @selector ( engine : changeView :)]) {
_event [ GLEngineChangeView ] = YES ;
}
}
@end
@interface MyGLEngineDelegate : NSObject < GLEngineDelegate > {
//
}
@end
@implementation MyGLEngineDelegate
- ( BOOL ) engine: ( Engine * ) engine changeView: ( GLView * ) view {
// change the view
}
@end
Object Pascal
A simple example
type
IDelegateInterface = interface
procedure Method1 ;
procedure Method2 ;
end ;
TClassA = class ( TInterfacedObject , IDelegateInterface )
public
procedure Method1 ;
procedure Method2 ;
end ;
TClassB = class ( TInterfacedObject , IDelegateInterface )
public
procedure Method1 ;
procedure Method2 ;
end ;
TClassDel = class ( TInterfacedObject , IDelegateInterface )
private
FInterface : IDelegateInterface ;
public
procedure Method1 ;
procedure Method2 ;
procedure ToClassA ;
procedure ToClassB ;
end ;
implementation
{TClassA}
procedure TClassA . Method1 ;
begin
Writeln ( 'TClassA.Method1' ) ;
end ;
procedure TClassA . Method2 ;
begin
Writeln ( 'TClassA.Method2' ) ;
end ;
{TClassB}
procedure TClassB . Method1 ;
begin
Writeln ( 'TClassB.Method1' ) ;
end ;
procedure TClassB . Method2 ;
begin
Writeln ( 'TClassB.Method2' ) ;
end ;
{TClassDel}
procedure TClassDel . Method1 ;
begin
FInterface . Method1 ;
end ;
procedure TClassDel . Method2 ;
begin
FInterface . Method2 ;
end ;
procedure TClassDel . ToClassA ;
begin
FInterface : = TClassA . Create ;
end ;
procedure TClassDel . ToClassB ;
begin
FInterface : = TClassB . Create ;
end ;
Nontrivial Example
This example is the Object Pascal version of the non-trivial example above.
unit UnitEmployeers ;
interface
uses
Contnrs
type
// Class for storing employee data
TEmployee = class
private
FName : string ;
FDepartament : string ;
public
constructor Create ( Name , Departament : string ) ;
published
property Name : string read FName ;
property Departament : string read FDepartament ;
end ;
// Class for storing the list of employees
TEmployeersList = class
private
// Object of class "list of objects"
FEmployeersList : TObjectList ;
function GetEmployee ( Index : Integer ) : TEmployee ;
procedure SetEmployee ( Index : Integer ; const Value : TEmployee ) ;
public
constructor Create ;
destructor Destroy ; override ;
function Add ( Employee : TEmployee ) : Integer ;
procedure Remove ( Employee : TEmployee ) ;
function IndexEmployeeByName ( Name : string ; Offset : Integer = 0 ) : Integer ;
property Employeers [ Index : Integer ] : TEmployee read GetEmployee write SetEmployee ; default ;
end ;
implementation
{TEmployee}
constructor TEmployee . Create ( Name , Departament : string ) ;
begin
FName : = Name ;
FDepartament : = Departament ;
end ;
{TEmployeersList}
constructor TEmployeersList . Create ;
begin
// Create an object whose methods we will delegate
FEmployeersList : = TObjectList . Create ;
end ;
destructor TEmployeersList . Destroy
begin
FEmployeersList . Free
inherited ;
end ;
function TEmployeersList . GetEmployee ( Index : Integer ) : TEmployee ;
begin
Result : = FEmployeersList [ Index ] as TEmployee ;
end ;
procedure TEmployeersList . SetEmployee ( Index : Integer ; const Value : TEmployee ) ;
begin
FEmployeersList [ Index ] : = Value ;
end ;
function TEmployeersList . IndexEmployeeByName ( Name : string ; Offset : Integer = 0 ) : Integer ;
// Sequential search for an employee by name
// Through the Offset argument, you can specify the position from which to search.
// If the employee is not found, it will return a value less than zero (-1)
var
Index : Integer ;
begin
Result : = - 1 ; // Assume It Is Not On The List
for Index : = FEmployeersList . Count - 1 downto Offset do
if ( FEmployeersList [ Index ] as TEmployee ) . Name = Name then
begin
Result : = Index ;
Exit
end ;
end ;
function TEmployeersList . Add ( Employee : TEmployee ) : Integer ;
begin
Result : = FEmployeersList . Add ( Employee ) ;
end ;
procedure TEmployeersList . Remove ( Employee : TEmployee ) ;
begin
FEmployeersList . Remove ( Employee ) ;
end ;
end .
Unfortunately, not all programmers use the delegation pattern. For example, Borland (the developer of the Delphi programming environment) in its standard class library inherited the aforementioned TObjectList object list class from the TList pointer list class . This caused discontent among some experienced programmers.
PHP5
A simple example
This example is a PHP version of the simple Java example above.
<? php
class A {
public function f () {
print "A: Call the f () method <br />" ;
}
public function g () {
print "A: Call the g () method <br />" ;
}
}
class C {
private $ _a ;
public function __construct () {
$ this -> _a = new A ;
}
public function f () {
$ this -> _a -> f ();
}
public function g () {
$ this -> _a -> g ();
}
public function y () {
print "C: call the y () method <br />" ;
}
}
$ obj = new C ;
$ obj -> f ();
$ obj -> g ();
$ obj -> y ();
?>
Complicated Example
This example is the PHP version of the sophisticated Java example above.
<? php
// use the interface for security type
interface I {
public function f ();
public function g ();
}
class A implements I {
public function f () {
print "A: Call the f () method <br />" ;
}
public function g () {
print "A: Call the g () method <br />" ;
}
}
class B implements I {
public function f () {
print "B: Call the f () method <br />" ;
}
public function g () {
print "B: Call the g () method <br />" ;
}
}
class C implements I {
private $ _i ;
// create an object whose methods we will delegate
public function __construct () {
$ this -> _i = new A ;
}
// with these methods we change the object field whose methods we will delegate
public function toA () {
$ this -> _i = new A ;
}
public function toB () {
$ this -> _i = new B ;
}
// delegated methods
public function f () {
$ this -> _i -> f ();
}
public function g () {
$ this -> _i -> g ();
}
}
$ obj = new C ;
$ obj -> f ();
$ obj -> g ();
$ obj -> toB ();
$ obj -> f ();
$ obj -> g ();
?>
Nontrivial Example
This example is a PHP version of the non-trivial example above.
<? php
// class for storing employee data
class Employee {
private $ _name ;
private $ _departament ;
public function __construct ( $ name , $ departament ) {
$ this -> _name = $ name ;
$ this -> _departament = $ departament ;
}
public function getName () {
return $ this -> _name ;
}
public function getDepartament () {
return $ this -> _departament ;
}
}
// class to store the list of objects
class ObjectList {
private $ _objList ;
public function __construct () {
$ this -> free ();
}
/ **
* not to be bored!
* /
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 ];
}
public function set ( $ index , $ obj ) {
$ this -> _objList [ $ index ] = $ obj ;
}
}
// class for storing employees
class EmployeeList {
// object of class "list of objects"
private $ _employeersList ;
public function __construct () {
// create an object whose methods we will delegate
$ 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 ( Employee $ objEmployer ) {
$ this -> _employeersList -> add ( $ objEmployer );
}
public function remove ( Employee $ objEmployer ) {
$ this -> _employeersList -> remove ( $ objEmployer );
}
// sequential search for an employee by name
// through the argument $ offset, you can specify the position from which to search.
// if the employee is not found, will return a value less than zero (-1)
public function getIndexByName ( $ name , $ offset = 0 ) {
$ result = - 1 ; // assume it is not in the list
$ cnt = $ this -> _employeersList -> count ();
for ( $ i = $ offset ; $ i < $ cnt ; $ i ++ ) {
if ( ! strcmp ( $ name , $ this -> _employeersList -> get ( $ i ) -> getName () ) ) {
$ result = $ i ;
break ;
}
}
return $ result ;
}
}
$ obj1 = new Employee ( "Tanasiychuk Stepan" , "web studio" );
$ obj2 = new Employee ( "Kusyy Nazar" , "web studio" );
$ obj3 = new Employee ( "Forty Orest" , "web studio" );
$ objList = new EmployeeList ();
$ objList -> add ( $ obj1 );
$ objList -> add ( $ obj2 );
$ objList -> add ( $ 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
A simple example
Python source code
#coding: utf-8
#python 3
class A :
def f ( self ):
print ( 'A: call method f' )
def g ( self ):
print ( 'A: call the g' method )
class C :
def __init__ ( self ):
self . A = A ()
def f ( self ):
return self . A. f ()
def g ( self ):
return self . A. g ()
c = C ()
c . f () #A: call the f method
c . g () #A: call the g method
JavaScript
A simple example
function A () {
this . f = function () {
alert ( "A: call the f () method" );
};
this . g = function () {
alert ( "A: call the g () method" );
};
}
function C () {
var a = new A ();
this . f = function () {
a . f ();
};
this . g = function () {
a . g ();
};
}
var c = new C ();
c . f (); // "A: call the f () method"
c . g (); // "A: call the g () method"
Complicated Example
function A () {
this . f = function () {
alert ( "A: call the f () method" );
};
this . g = function () {
alert ( "A: call the g () method" );
};
}
function B () {
this . f = function () {
alert ( "B: call the f () method" );
};
this . g = function () {
alert ( "B: call the g () method" );
};
}
function C () {
// instantiate A and B
var a = new A ();
var b = new B ();
var cur = a ; // link to the current object with the implementation of methods; default is A
this . toA = function () {
cur = a ;
};
this . toB = function () {
cur = b ;
};
this . f = function () {
cur . f ();
};
this . g = function () {
cur . g ();
};
}
var c = new C ();
c . f (); // "A: call the f () method"
c . g (); // "A: call the g () method"
c . toB ();
c . f (); // "B: call the f () method"
c . g (); // "B: call the g () method"
Nontrivial Example
function Employee ( name , departament ) {
this . getName = function () {
return name ;
};
this . getDepartament = function () {
return departament ;
};
this . toString = function () {
// convert to string for convenient debugging
return "Employee" + name + "," + departament ;
};
}
function EmployeesList () {
var employees = [];
this . add = function () {
// function takes an arbitrary number of arguments
for ( var i = 0 , l = arguments . length ; i < l ; i ++ ) {
if ( arguments [ i ]. constructor == Employee ) {
// type check
employees . push ( arguments [ i ]);
}
}
};
this . set = function ( obj , index ) {
if ( obj . constructor == Employee ) {
delete employees [ index ];
employees [ index ] = obj ;
}
};
this . remove = function ( obj ) {
for ( var i = 0 , l = employees . length ; i < l ; i ++ ) {
if ( employees [ i ] == obj ) {
employees . splice ( i , 1 );
i - ;
l - ;
}
}
};
this . getByIndex = function ( num ) {
return employees [ num ];
};
this . getIndexByName = function ( name , offset ) {
// sequential search for an employee by name
// through the offset argument, you can specify the position from which to search. (default 0)
// if the employee is not found, will return -1
for ( var i = offset || 0 , l = employees . length ; i < l ; i ++ ) {
if ( employees [ i ]. getName () == name ) return i ;
}
return - 1 ;
};
this . toString = function () {
// ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π² ΡΡΡΠΎΠΊΡ Π΄Π»Ρ ΡΠ΄ΠΎΠ±Π½ΠΎΠ³ΠΎ Π΄Π΅Π±Π°Π³Π°
var ret = "" ;
for ( var i = 0 , l = employees . length ; i < l ; i ++ ) {
ret += i + ": " + employees [ i ] + "\n" ;
}
return ret ;
};
}
var o1 = new Employee ( "Π’Π°Π½Π°ΡΠΈΠΉΡΡΠΊ Π‘ΡΠ΅ΠΏΠ°Π½" , "web ΡΡΡΠ΄ΠΈΡ" );
var o2 = new Employee ( "ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ" , "web ΡΡΡΠ΄ΠΈΡ" );
var o3 = new Employee ( "Π‘ΠΎΡΠΎΠΊΠ° ΠΡΠ΅ΡΡ" , "web ΡΡΡΠ΄ΠΈΡ" );
var emps = new EmployeesList ();
emps . add ( o1 , o2 , o3 ); // ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ ΠΈ ΠΏΠΎ-ΠΎΠ΄ΠΈΠ½ΠΎΡΠΊΠ΅
alert ( emps ); // "0: Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ Π’Π°Π½Π°ΡΠΈΠΉΡΡΠΊ Π‘ΡΠ΅ΠΏΠ°Π½, web ΡΡΡΠ΄ΠΈΡ
// 1: Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ, web ΡΡΡΠ΄ΠΈΡ
// 2: Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ Π‘ΠΎΡΠΎΠΊΠ° ΠΡΠ΅ΡΡ, web ΡΡΡΠ΄ΠΈΡ"
var obj4 = emps . getByIndex ( emps . getIndexByName ( "ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ" ) ); // ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΡΡΠ»ΠΊΡ Π½Π° ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ°
alert ( obj4 ); // "Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ, web ΡΡΡΠ΄ΠΈΡ"
emps . set ( obj4 , 2 ); // Π²ΠΌΠ΅ΡΡΠΎ 2Π³ΠΎ (ΠΎΡ Π½ΠΎΠ»Ρ) ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ° Π²ΡΡΠ°Π²Π»ΡΠ΅ΠΌ obj4
alert ( emps ); // "0: Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ Π’Π°Π½Π°ΡΠΈΠΉΡΡΠΊ Π‘ΡΠ΅ΠΏΠ°Π½, web ΡΡΡΠ΄ΠΈΡ
// 1: Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ, web ΡΡΡΠ΄ΠΈΡ
// 2: Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ, web ΡΡΡΠ΄ΠΈΡ"
emps . remove ( obj4 ); // ΡΠ΄Π°Π»ΡΠ΅ΠΌ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ° obj4
alert ( emps ); // "0: Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ Π’Π°Π½Π°ΡΠΈΠΉΡΡΠΊ Π‘ΡΠ΅ΠΏΠ°Π½, web ΡΡΡΠ΄ΠΈΡ"
VB.NET
Π‘Π»ΠΎΠΆΠ½ΡΠΉ ΠΏΡΠΈΠΌΠ΅Ρ
Namespace Patterns
Interface I
Sub f ()
Sub g ()
End Interface
Class A
Implements I
Public Sub f () Implements I . f
System . Console . WriteLine ( "A: Π²ΡΠ·ΡΠ²Π°Π΅ΠΌ ΠΌΠ΅ΡΠΎΠ΄ f()" )
End Sub
Public Sub g () Implements I . g
System . Console . WriteLine ( "A: Π²ΡΠ·ΡΠ²Π°Π΅ΠΌ ΠΌΠ΅ΡΠΎΠ΄ g()" )
End Sub
End Class
Class B
Implements I
Public Sub f () Implements I . f
System . Console . WriteLine ( "B: Π²ΡΠ·ΡΠ²Π°Π΅ΠΌ ΠΌΠ΅ΡΠΎΠ΄ f()" )
End Sub
Public Sub g () Implements I . g
System . Console . WriteLine ( "B: Π²ΡΠ·ΡΠ²Π°Π΅ΠΌ ΠΌΠ΅ΡΠΎΠ΄ g()" )
End Sub
End Class
Class C
Implements I
' Π‘ΠΎΠ·Π΄Π°ΡΠΌ ΠΎΠ±ΡΠ΅ΠΊΡ, ΠΌΠ΅ΡΠΎΠ΄Ρ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π±ΡΠ΄Π΅ΠΌ Π΄Π΅Π»Π΅Π³ΠΈΡΠΎΠ²Π°ΡΡ
Private i As I = New A ()
Public Sub f () Implements i . f
i . f ()
End Sub
Public Sub g () Implements i . g
i . g ()
End Sub
' ΠΡΠΈΠΌΠΈ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌΠΈ ΠΌΠ΅Π½ΡΠ΅ΠΌ ΠΏΠΎΠ»Π΅-ΠΎΠ±ΡΠ΅ΠΊΡ, ΡΡΠΈ ΠΌΠ΅ΡΠΎΠ΄Ρ Π±ΡΠ΄Π΅ΠΌ Π΄Π΅Π»Π΅Π³ΠΈΡΠΎΠ²Π°ΡΡ
Public Sub toA ()
i = New A ()
End Sub
Public Sub toB ()
i = New B ()
End Sub
End Class
Class DelegatePattern
Shared Sub Main ()
Dim c As New C ()
c . f ()
c . g ()
c . toB ()
c . f ()
c . g ()
System . Console . ReadKey ()
End Sub
End Class
End Namespace
ΠΠ΅ΡΡΠΈΠ²ΠΈΠ°Π»ΡΠ½ΡΠΉ ΠΏΡΠΈΠΌΠ΅Ρ
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Namespace Employees
''' <summary>
''' ΠΠ»Π°ΡΡ Π΄Π»Ρ Ρ
ΡΠ°Π½Π΅Π½ΠΈΡ Π΄Π°Π½Π½ΡΡ
ΠΎ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ΅.
''' </summary>
Class Employee
Private m_name As String
Private m_department As String
Public Sub New ( ByVal name As String , ByVal departament As String )
Me . m_name = name
Me . m_department = departament
End Sub
''' <summary>
''' ΠΠΌΡ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ°.
''' </summary>
Public ReadOnly Property Name () As String
Get
Return Me . m_name
End Get
End Property
''' <summary>
''' ΠΡΠ΄Π΅Π» ΡΠ°Π±ΠΎΡΡ.
''' </summary>
Public ReadOnly Property Department () As String
Get
Return Me . m_department
End Get
End Property
End Class
''' <summary>
''' ΠΠ»Π°ΡΡ Π΄Π»Ρ Ρ
ΡΠ°Π½Π΅Π½ΠΈΡ ΡΠΏΠΈΡΠΊΠ° ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠΎΠ².
''' </summary>
Class EmployeesList
Private employees As New List ( Of Employee )()
''' <summary>
''' Π‘Π²ΠΎΠΉΡΡΠ²ΠΎ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ ΠΈ Π·Π°ΠΏΠΈΡΠΈ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ° ΠΏΠΎ ΠΈΠ½Π΄Π΅ΠΊΡΡ.
''' </summary>
''' <param name="index">ΠΠ½Π΄Π΅ΠΊΡ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ°.</param>
''' <returns>Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ.</returns>
Default Public Property Item ( ByVal index As Integer ) As Employee
Get
Return employees ( index )
End Get
Set ( ByVal value As Employee )
employees ( index ) = value
End Set
End Property
''' <summary>
''' ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ°.
''' </summary>
''' <param name="employee">ΠΠΎΠ²ΡΠΉ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊ.</param>
Public Sub Add ( ByVal employee As Employee )
employees . Add ( employee )
End Sub
''' <summary>
''' Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠ΅Π³ΠΎ ΡΡΠΎΡΡΠ΄Π½ΠΈΠΊΠ°.
''' </summary>
''' <param name="employee">Π‘ΠΎΡΡΡΠ΄Π½ΠΈΠΊ Π΄Π»Ρ ΡΠ΄Π°Π»Π΅Π½ΠΈΡ.</param>
Public Sub Remove ( ByVal employee As Employee )
employees . Remove ( employee )
End Sub
''' <summary>
''' ΠΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΡΠΉ ΠΏΠΎΠΈΡΠΊ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ° ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ.
''' </summary>
''' <param name="name">ΠΠΌΡ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ°.</param>
''' <returns>ΠΠ½Π΄Π΅ΠΊΡ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ°.</returns>
Public Function GetIndexOfEmployeeByName ( ByVal name As String ) As Integer
Dim index As Integer = - 1
For i As Integer = 0 To employees . Count - 1
If employees ( i ). Name = name Then
index = i
Exit For
End If
Next
Return index
End Function
''' <summary>
''' ΠΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΡΠΉ ΠΏΠΎΠΈΡΠΊ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ° ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ.
''' </summary>
''' <param name="name">ΠΠΌΡ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ°.</param>
''' <param name="offset">ΠΠΎΠ·ΠΈΡΠΈΡ, Ρ ΠΊΠΎΡΠΎΡΠΎΠΉ ΡΠ»Π΅Π΄ΡΠ΅Ρ Π½Π°ΡΠΈΠ½Π°ΡΡ ΠΏΠΎΠΈΡΠΊ.</param>
''' <returns>ΠΠ½Π΄Π΅ΠΊΡ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ°.</returns>
Public Function GetIndexOfEmployeeByName ( ByVal name As String , ByVal offset As Integer ) As Integer
Dim index As Integer = - 1
For i As Integer = offset To employees . Count - 1
If employees ( i ). Name = name Then
index = i
Exit For
End If
Next
Return index
End Function
End Class
Class Program
Shared Sub Main ()
'Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠΏΠΈΡΠΊΠ° ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠΎΠ² ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π·Π°ΠΏΠΈΡΠ΅ΠΉ Π² Π½Π΅Π³ΠΎ
Dim empList As New EmployeesList ()
empList . Add ( New Employee ( "Π¨Π»ΡΠ½ΡΠΊΠΈΠΉ ΠΠΌΠΈΡΡΠΈΠΉ" , "web ΡΡΡΠ΄ΠΈΡ" ))
empList . Add ( New Employee ( "ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ" , "web ΡΡΡΠ΄ΠΈΡ" ))
empList . Add ( New Employee ( "Π‘ΠΎΡΠΎΠΊΠ° ΠΡΠ΅ΡΡ" , "web ΡΡΡΠ΄ΠΈΡ" ))
'ΠΠΎΠΈΡΠΊ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ° ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ ΠΈ Π²ΡΠ²ΠΎΠ΄ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ° ΠΏΡΠΈ ΠΏΠΎΠΈΡΠΊΠ΅ Ρ Π½Π°ΡΠ°Π»Π° ΠΈ ΡΠΎ 2-ΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ
Console . WriteLine ( empList . GetIndexOfEmployeeByName ( "ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ" ). ToString ())
Console . WriteLine ( empList . GetIndexOfEmployeeByName ( "ΠΡΡΡΠΉ ΠΠ°Π·Π°Ρ" , 2 ). ToString ())
'ΠΠΎΠΈΡΠΊ ΠΈ ΡΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠ° Π‘ΠΎΡΠΎΠΊΠ° ΠΡΠ΅ΡΡ
empList . Remove ( empList ( empList . GetIndexOfEmployeeByName ( "Π‘ΠΎΡΠΎΠΊΠ° ΠΡΠ΅ΡΡ" )))
Console . Read ()
End Sub
End Class
End Namespace
See also
- Π¨Π°Π±Π»ΠΎΠ½Ρ ΠΏΡΠΎΠ΅ΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ
- ΠΠΎΡΡ-ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΠΎΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅
Notes
- β ΠΡΡΡ ΠΠΊΠΊΠ΅Π»Ρ. Π€ΠΈΠ»ΠΎΡΠΎΡΠΈΡ Java. β 4-Π΅ ΠΈΠ·Π΄Π°Π½ΠΈΠ΅. β ΠΠΠ ΠΠ·Π΄Π°ΡΠ΅Π»ΡΡΡΠ²ΠΎ "ΠΠΈΡΠ΅Ρ", 2016. β Π‘. 215. β 1165 Ρ.
Literature
- ΠΠΆΡΠ»ΠΈΠ°Π½ ΠΠ°ΠΊΠ½Π΅Π»Π» Β«Π€ΡΠ½Π΄Π°ΠΌΠ΅Π½ΡΠ°Π»ΡΠ½ΡΠ΅ Π°Π»Π³ΠΎΡΠΈΡΠΌΡ ΠΈ ΡΡΡΡΠΊΡΡΡΡ Π΄Π°Π½Π½ΡΡ Π² DelphiΒ». Ed. DiaSoft 2003 Π³ΠΎΠ΄
- ΠΡΠ°Π½Π΄ Π. Β«Π¨Π°Π±Π»ΠΎΠ½Ρ ΠΏΡΠΎΠ΅ΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π² JavaΒ». 2004
- ΠΡΡΡ ΠΠΊΠΊΠ΅Π»Ρ "Π€ΠΈΠ»ΠΎΡΠΎΡΠΈΡ Java". Ed. "ΠΠΈΡΠ΅Ρ" 2016 Π³ΠΎΠ΄