Prototype (designmønster)
Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den
version , der blev gennemgået den 9. marts 2016; checks kræver
11 redigeringer .
Prototype , ( eng. Prototype ) -genererende designmønster .
Udnævnelse
Angiver den slags objekter, der skal oprettes ved hjælp af en prototypeinstans og opretter nye objekter ved at kopiere denne prototype. Det giver dig mulighed for at komme væk fra implementeringen og giver dig mulighed for at følge princippet om "programmering gennem grænseflader". En grænseflade/abstrakt klasse øverst i hierarkiet er angivet som den returnerende type, og efterkommerklasser kan erstatte en arving, der implementerer denne type der.
Kort sagt er dette mønsteret for at skabe et objekt ved at klone et andet objekt i stedet for at skabe det gennem en konstruktør.
Ansøgning
Mønsteret bruges til at:
- at undgå yderligere bestræbelser på at skabe et objekt på en standard måde (hvilket betyder brugen af en konstruktør, da konstruktørerne i hele hierarkiet af objektets forfædre også vil blive kaldt), når dette er uoverkommeligt dyrt for applikationen.
- undgå at arve objektskaberen i klientapplikationen, som det abstrakte fabriksmønster gør .
Brug dette designmønster, når systemet er ligeglad med, hvordan produkter skabes, pakkes og præsenteres i det:
- instansierede klasser bestemmes ved kørselstid, for eksempel ved dynamisk belastning;
- undgå at bygge klassehierarkier eller fabrikker parallelt med produktklassehierarkiet;
- klasseforekomster kan være i en af flere forskellige tilstande. Det kan være mere praktisk at indstille det passende antal prototyper og klone dem i stedet for manuelt at instansiere klassen i den passende tilstand hver gang.
Eksempler
Python-eksempel
Kildekode i Python
#!/usr/bin/env python
# -*- kodning: utf-8 -*-
import kopi
klasse prototype :
def __init__ ( selv ):
selv . _objekter = {}
def register_object ( selv , navn , obj ):
"""Registrer et objekt"""
selv . _objekter [ navn ] = obj
def unregister_object ( selv , navn ):
"""Afregistrer et objekt"""
del selv . _objekter [ navn ]
def clone ( selv , navn , ** attr ):
"""Klon et registreret objekt og opdater indre attributordbog"""
obj = kopi . deepcopy ( selv . _objekter . få ( navn ))
obj . __dikt__ . opdatere ( attr )
returnere obj
klasse A :
def __init__ ( selv ):
selv . x = 3
selv . y = 8
selv . z = 15
selv . skrald = [ 38 , 11 , 19 ]
def __str__ ( selv ):
returner ' {} {} {} {} ' . format ( selv . x , selv . y , selv . z , selv . skrald )
def main ():
a = A ()
prototype = Prototype ()
prototype . register_object ( 'objecta' , a )
b = prototype . klon ( 'objecta' )
c = prototype . clone ( 'objecta' , x = 1 , y = 2 , garbage = [ 88 , 1 ])
print ([ str ( i ) for i in ( a , b , c )])
if __name__ == '__main__' :
main ()
- OUTPUT ###
- ['3 8 15 [38, 11, 19]', '3 8 15 [38, 11, 19]', '1 2 15 [88, 1]']
C++ eksempel
Kildetekst i C++
klasse måltid {
offentligt :
virtuelt ~ måltid ();
virtual void eat () = 0 ;
virtuelt måltid * klon () const = 0 ;
//...
};
klasse Spaghetti : offentligt måltid {
offentligt :
Spaghetti ( konst Spaghetti & );
void spise ();
Spaghetti * clone () const { returnere ny Spaghetti ( * this ); }
//...
};
Java-eksempel
Java kilde
/**
* Prototype Klasse
*/
offentlig klasse Cookie implementerer Klonbar {
beskyttet int vægt ;
@Override
public Cookie klon () kaster CloneNotSupportedException {
Cookie copy = ( Cookie ) super . klon ();
//I en faktisk implementering af dette mønster kan du nu ændre referencer til
//det dyre at producere dele fra de kopier, der opbevares inde i prototypen.
returnere kopi ;
}
}
/**
* Konkrete prototyper til kloning
*/
offentlig klasse CoconutCookie udvider Cookie { }
/**
* Klientklasse
*/
offentlig klasse CookieMachine {
privat Cookie- cookie ; // Kunne have været en privat kloningsbar cookie.
offentlig CookieMachine ( Cookie - cookie ) {
dette . cookie = cookie _
}
public Cookie makeCookie () kaster CloneNotSupportedException {
returner ( Cookie ) dette . cookie . klon ();
}
public static void main ( String args [] ) kaster CloneNotSupportedException {
Cookie tempCookie = null ;
Cookie prot = ny CoconutCookie ();
CookieMachine cm = ny CookieMachine ( prot );
for ( int i = 0 ; i < 100 ; i ++ )
tempCookie = cm . laveCookie ();
}
}
Scala eksempel
Scala kildekode
package.com _
pakkeobjekt prototype { _
class Waffle (
protected var name : String ,
protected var primaryFyld : String ,
protected var specialFilling : Option [ String ] = Ingen
)
udvider Cloneable {
tilsidesæt def klon (): Vaffel = {
super . klon (). asInstanceOf [ Waffle ]
}
def output () : Enhed = {
println ( s"Waffle $ navn med primær fyldning $ primaryFyld "
+ ( if ( specialFyld != Ingen ) specialFyld . get else "" ))
}
}
objekt PrototypeTest {
def main ( args : Array [ String ]) : Enhed = {
println ( "Output:" )
val chocolateWaffle = new Waffle ( "ChocolateWaffle" , "Chocolate" )
chocolateWaffle . output ()
chokoladeVaffel . klon (). output ()
val coconutWaffle = new vaffel ( "CoconutWaffle" , "Kondenseret mælk" , Nogle ( "Coconut" ) ))
coconutWaffle . output ()
coconutWaffle . klon (). output ()
}
}
}
// Output:
// VaffelchokoladeVaffel med primært fyld Chokolade // VaffelchokoladeVaffel med
primært fyld Chokolade
// Vaffel KokosVaffel med primært fyld Kondenseret mælkKokos
// Vaffel KokosVaffel med primært fyld Kondenseret mælkKokosnød
Eksempel i C#
Kildetekst i C#
bruger System ;
namespace Prototype
{
class MainApp
{
static void Main ()
{
// Opret to forekomster og klon hver
Prototype prototype1 = new ConcretePrototype1 ( "I" );
Prototype clonedPrototype1 = prototype1 . klon ();
Konsol . WriteLine ( "Clone: {0}" , clonedPrototype1 . Id );
Prototype prototype2 = ny ConcretePrototype2 ( "II" );
Prototype clonedPrototype2 = prototype2 . klon ();
Konsol . WriteLine ( "Klonet: {0}" , klonet Prototype2 . Id );
}
}
// "Prototype"
public abstract class Prototype
{
// Constructor
public Prototype ( string id )
{
this . id = id ;
Konsol . Skriv ( "Base constructor kaldes." );
}
// Property
public string Id { get ; privat sæt ; }
public virtual Prototype Clone ()
{
// Shallow copy
return ( Prototype ) this . MemberwiseClone ();
}
}
// "ConcretePrototype1"
public class ConcretePrototype1 : Prototype
{
// Constructor
public ConcretePrototype1 ( string id ) : base ( id )
{
}
}
// "ConcretePrototype2"
public class ConcretePrototype2 : Prototype
{
// Constructor
public ConcretePrototype2 ( string id ) : base ( id )
{
}
}
}
PHP eksempel
PHP kildekode
<?php
/**
* Hierarki af gyldige klasser til prototyping
*/
abstrakt klasse Terræn {}
abstrakt klasse Hav udvider Terræn {}
klasse JordHav udvider Hav {}
klasse MarsHav udvider Hav {}
klasse VenusHav udvider Hav {}
abstrakt klasse Plains udvider Terræn {}
klasse EarthPlains udvider Plains {}
klasse MarsPlains udvider Plains {}
klasse VenusPlains udvider Plains {}
abstrakt klasse Skov udvider Terræn {}
klasse EarthForest udvider Skov {}
klasse MarsForest udvider Skov {}
klasse VenusForest udvider Skov {}
/**
* Definer prototype fabrikslogik
*/
klasse TerrainFactory {
private $sea ;
privat $skov ;
private $sletten ;
public function __construct ( Hav $sea , Plains $plains , Forest $forest ) {
$this -> sea = $sea ;
$this -> plains = $plains ;
$dette -> skov = $skov ;
}
funktion getSea ( ) {
return clone $this -> sea ;
}
funktion getPlains ( ) {
return clone $this -> plains ;
}
funktion getForest ( ) {
return clone $this -> forest ;
}
}
/**
* Opret en fabrik med de givne prototypeparametre
*/
$prototypeFactory = ny TerrainFactory (
ny EarthSea (),
ny MarsPlains (),
ny VenusForest ()
);
/**
* Opret de givne objekter ved at klone
*/
$sea = $prototypeFactory -> getSea ();
$plains = $prototypeFactory -> getPlains ();
$skov = $prototypeFactory -> getForest ();
Ruby eksempel
Ruby kildekode
modul prototype
# "prototype"
klasse prototype
# Ejendom
# egenskaben id er oprindeligt til stede for hvert objekt, så vi vil bruge egenskaben navn
attr_reader :navn
# konstruktør
def initialisere navn
@navn = navn
slut
ende
ende
# Opret en instans og klon den
p1 = Prototype :: Prototype . nyt "mit navn" # Prototype-klasseobjektet oprettes på traditionel måde - ved metoden new
p2 = p1 . clone # klonmetoden findes på hvert objekt som standard - det behøver ikke at være defineret
sætter "p1.id = #{ p1 . objekt_id } , p2.id = #{ p2 . objekt_id } " # forskellige id'er vil blive udskrevet
sætter "p1.navn = #{ p1 . navn } , p2.navn = #{ p2 . name } " # identiske navne vil blive udskrevet - "mit navn"
# Vent på, at brugeren
får
VB.NET eksempel
Kildetekst på VB.NET sprog
Namespace Prototype
Klasse MainApp
Shared Sub Main ()
' Opret to forekomster og klon hver
Dim p1 As Prototype = New ConcretePrototype1 ( "I" )
Dim c1 As Prototype = p1 . Klon ()
konsol . WriteLine ( "Klon: {0}" , c1 . Id )
Dim p2 As Prototype = New ConcretePrototype2 ( "II" )
Dim c2 As Prototype = p2 . Klon ()
konsol . WriteLine ( "Klon: {0}" , c2 . Id )
Konsol . Læs ()
End Sub
End Class
"Prototype"
MustInherit Class Prototype
Private m_id As String
' Constructor
Public Sub New ( ByVal id As String )
Me . m_id = id
End Sub
'
Public ReadOnly Property Id () As String
Get
Return m_id
End Get
End Property
Offentlig MustOverride Funktion Klon ( ) Som Prototype
Slutklasse
' "Betonprototype1"
Klasse BetonPrototype1
Arver Prototype
' Constructor
Public Sub New ( ByVal id As String )
MyBase . Ny ( id )
End Sub
Offentlige tilsidesættelser Funktion Klon () Som prototype
' Ufuldstændig kopi
Returner DirectCast ( Mig . MemberwiseClone ( ) , Prototype )
Slutfunktion Slutklasse
' "Betonprototype2"
Klasse ConcretePrototype2
arver prototype
' Constructor
Public Sub New ( ByVal id As String )
MyBase . Ny ( id )
End Sub
Offentlige tilsidesættelser Funktion Klon () Som prototype
' Ufuldstændig
kopi Returner DirectCast ( Mig . MemberwiseClone ( ) , Prototype )
Slutfunktion Slutningsklasse Slutnavneområde
Delphi eksempel
Kildetekst i Delphi
program PrototypePattern ;
{$APPTYPE KONSOL}
bruger
SysUtils ;
type
TPrototype = klasse
offentlig
funktion Klon : TPrototype ; virtuel ; abstrakt ;
ende ;
type
TPrototypeType = klasse ( TPrototype )
privat
FID : Heltal ;
FInfo : String ;
public
property ID : Heltal læs FID skriv FID ;
ejendom Info : Streng læs FIinfo skriv FIinfo ;
funktion Klon : TPrototype ; tilsidesætte ;
ende ;
funktion TPrototypeType . Klon : T Prototype ;
var
vClone : TPrototypeType ;
start
vClone := TPrototypeType . skabe ;
vClone . ID := ID ;
vClone . Info := Info ;
Resultat := vClone ;
ende ;
procedure CloneAndShow ( Prototype : TPrototypeType ) ;
var
vClone : TPrototypeType ;
start
vClone := Prototype . klon ;
prøv
Skriv ( vClone . ID ) ;
Skriv ( vClone.Info ) ; _ _ endelig vClone . Gratis ; ende ;
WriteLn ;
ende ;
var
vConcretePrototype1 , vConcretePrototype2 : TPrototypeType ;
start
vConcretePrototype1 := TPrototypeType . skabe ;
vConcretePrototype2 := TPrototypeType . skabe ;
prøv
vConcretePrototype1 . ID := 10 ;
vConcretePrototype1 . Info := 'Prototype1!' ;
vConcretePrototype2 . ID := 11 ;
vConcretePrototype2 . Info := 'Prototype2!' ;
CloneAndShow ( vConcretePrototype1 ) ;
CloneAndShow ( vConcretePrototype2 ) ;
endelig
vConcretePrototype1 . Gratis ;
vConcretePrototype2 . Gratis ;
ende ;
Læsln ;
ende .
CoffeeScript-eksempel
CoffeeScript eksempel
klasse PresidentPrototype -
konstruktør: (@proto) ->
klon: ->
kunde = ny præsident ()
customer.first = @proto . første kunde.sidste
= @proto . sidste kunde.aka
= @proto . a.k. en
kunde
klasse Præsident
konstruktør: (@first, @last, @aka) -> sig
: -> konsol . log "Hans navn er #{ @first } #{ @last } aka #{ @aka } ."
run = ->
proto = ny præsident ( "Jimmy" , "Wales" , "Jimbo" )
prototype = ny præsidentPrototype ( proto )
kunde = prototype . klone ()
kunde . sige ()
løb ()
Io eksempel
Io kildekode
Foo := Objekt klon
Foo smth := 2
Bar := Foo klon
Litteratur
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Teknikker til objektorienteret design. Designmønstre = Designmønstre: Elementer af genanvendelig objektorienteret software. - Sankt Petersborg. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (også ISBN 5-272-00355-1 )
Se også
Links