Prototyyppi (suunnittelumalli)
Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 9. maaliskuuta 2016 tarkistetusta
versiosta . tarkastukset vaativat
11 muokkausta .
Prototyyppi , ( eng. Prototype ) - generoiva suunnittelukuvio .
Tapaaminen
Määrittää prototyyppiinstanssilla luotavien objektien tyypit ja luo uusia objekteja kopioimalla tämän prototyypin. Sen avulla voit päästä eroon toteutuksesta ja voit seurata "ohjelmoinnin rajapintojen kautta" -periaatetta. Hierarkian huipulla oleva rajapinta/abstrakti luokka on määritetty palautuvaksi tyypiksi, ja jälkeläisluokat voivat korvata perillisen, joka toteuttaa tämän tyypin siellä.
Yksinkertaisesti sanottuna tämä on malli, jossa objekti luodaan kloonaamalla toinen objekti sen sijaan, että se luodaan rakentajan avulla.
Sovellus
Mallia käytetään:
- välttämään ylimääräisiä ponnisteluja objektin luomiseksi normaalilla tavalla (eli konstruktorin käyttöä, koska tässä tapauksessa kutsutaan myös koko objektin esivanhempien hierarkian rakentajia), kun tämä on sovellukselle kohtuuttoman kallista.
- Vältä objektin luojan perimistä asiakassovelluksessa, kuten abstrakti tehdasmalli tekee .
Käytä tätä suunnittelumallia, kun järjestelmä ei välitä siitä, miten tuotteet luodaan, pakataan ja esitetään siinä:
- instantoidut luokat määritetään ajon aikana, esimerkiksi dynaamisen lataamisen avulla;
- vältä luokkahierarkioiden tai tehtaiden rakentamista rinnakkain tuoteluokkahierarkian kanssa;
- luokan ilmentymät voivat olla jossakin useista eri tiloista. Saattaa olla kätevämpää asettaa sopiva määrä prototyyppejä ja kloonata ne sen sijaan, että luokka instantoidaan manuaalisesti oikeaan tilaan joka kerta.
Esimerkkejä
Python-esimerkki
Lähdekoodi Pythonissa
#!/usr/bin/env python
# -*- koodaus: utf-8 -*-
tuontikopio _
luokan prototyyppi :
def __init__ ( itse ):
itse . _objects = {}
def register_object ( self , name , obj ):
"""Rekisteröi objekti"""
self . _objektit [ nimi ] = objekti
def unregister_object ( self , name ):
"""Peruuta objektin rekisteröinti"""
del self . _objektit [ nimi ]
def clone ( self , name , ** attr ):
"""Kloonaa rekisteröity objekti ja päivitä sisäinen attribuuttisanakirja"""
obj = kopioi . syväkopio ( itse . _objektit . saada ( nimi ))
obj . __sane__ . päivitä ( attr )
return obj
luokka A :
def __init__ ( itse ):
itse . x = 3
itse . y = 8
itse . z = 15
itse . roskat = [ 38 , 11 , 19 ]
def __str__ ( itse ):
palauttaa ' {} {} {} {} ' . muoto ( itse . x , itse . y , itse . z , itse . roska )
def main ():
a = A ()
prototyyppi = Prototyyppi ()
prototyyppi . register_object ( 'objekti' , a )
b = prototyyppi . klooni ( 'objekti' )
c = prototyyppi . klooni ( 'objekti' , x = 1 , y = 2 , roska = [ 88 , 1 ])
tulosta ([ str ( i ) for i in ( a , b , c )])
if __name__ == '__main__' :
main ()
- TULOS ###
- ['3 8 15 [38, 11, 19]", "3 8 15 [38, 11, 19]", "1 2 15 [88, 1]"]
C++ esimerkki
Lähdeteksti C++:ssa
luokan ateria {
julkinen :
virtuaalinen ~ ateria ();
virtuaalinen tyhjä syö () = 0 ;
virtuaalinen ateria * klooni () const = 0 ;
//...
};
luokan spagetti : julkinen ateria {
julkinen :
Spagetti ( const Spaghetti & );
tyhjä syö ();
Spagetti * klooni () const { return new Spaghetti ( * this ); }
//...
};
Java-esimerkki
Java lähde
/**
* Prototyyppiluokka
*/
julkinen luokka Eväste toteuttaa Kloonattavissa {
suojattu sisäpaino ; _
@Override
public Evästeklooni ( ) heittää CloneNotSupportedException { Cookie copy = ( Cookie ) super . klooni ();
//Tämän mallin todellisessa toteutuksessa voit nyt muuttaa viittauksia
//kalleihin osien tuottamiseen prototyypin sisällä olevista kopioista.
palautuskopio ; _ } }
/**
* Kloonattavat konkreettiset prototyypit
*/
julkinen luokka CoconutCookie laajentaa evästettä { }
/**
* Asiakasluokka
*/
julkinen luokka CookieMachine {
yksityinen Evästeeväste ; _ // Olisi voinut olla yksityinen kloonattava eväste.
public CookieMachine ( Cookie cookie ) {
this . eväste = eväste _
}
public Cookie makeCookie () heittää CloneNotSupportedException {
return ( Cookie ) this . eväste . klooni ();
}
public static void main ( String args [ ] ) heittää CloneNotSupportedException {
Cookie tempCookie = null ;
Cookie prot = uusi CoconutCookie ();
CookieMachine cm = uusi CookieMachine ( prot );
for ( int i = 0 ; i < 100 ; i ++ )
tempCookie = cm . makeCookie ();
}
}
Scala esimerkki
Scala lähdekoodi
package.com _
pakettiobjektin prototyyppi { _
luokka Vohveli (
suojattu var - nimi : merkkijono ,
suojattu var ensisijainen Täyte : merkkijono ,
suojattu var erityinenTäyttö : Optio [ String ] = Ei mitään
)
extends Kloonattavissa {
ohita def- klooni (): Vohveli = {
super . klooni (). asInstanceOf [ Vohveli ]
}
def output () : Yksikkö = {
println ( s" vohvelin $ nimi ensisijaisella täytteellä $ ensisijainen täyttö " + ( if ( specialFilling != Ei mitään ) specialFilling . get else "" )) } }
object PrototypeTest {
def main ( args : Array [ String ]) : Yksikkö = {
println ( "Tuloste:" )
val chocolateWaffle = uusi Vohveli ( "SuklaaWaffle" , "Suklaa" )
chocolateWaffle . tulos ()
suklaavohveli . klooni (). output ()
val coconutWaffle = uusi Vohveli ( "CoconutWaffle" , "Condensed milk" , Some ( "Coconut" ) ))
coconutWaffle . lähtö ()
kookosvohveli . klooni (). lähtö ()
}
}
}
.
_
_
_
_
Esimerkki C#:ssa
Lähdeteksti C#
käyttäen System ;
nimitila Prototyyppi
{
class MainApp
{
static void Main ()
{
// Luo kaksi esiintymää ja kloonaa jokainen
prototyyppi prototyyppi1 = new ConcretePrototype1 ( "I" );
Prototyyppi kloonattuPrototyyppi1 = prototyyppi1 . klooni ();
konsoli . WriteLine ( "Klooni: {0}" , kloonattuPrototyyppi1 . Id );
Prototyyppi prototyyppi2 = uusi ConcretePrototype2 ( "II" );
Prototyyppi kloonattuPrototyyppi2 = prototyyppi2 . klooni ();
konsoli . WriteLine ( "Kloonattu: {0}" , kloonattuPrototyyppi2 . Id );
}
}
// "Prototyyppi"
public abstrakti luokka Prototyyppi
{
// Rakentaja
public Prototype ( string id )
{
this . id = id ;
konsoli . Write ( "Peruskonstruktori kutsutaan." );
}
// Omaisuuden
julkinen merkkijono Id { get ; yksityinen sarja ; }
public virtual Prototype Clone ()
{
// Matala kopio
palauttaa ( Prototype ) this . MemberwiseClone ();
}
}
// "ConcretePrototype1"
public class ConcretePrototype1 : Prototype
{
// Rakentaja
public ConcretePrototype1 ( string id ) : base ( id )
{
}
}
// "ConcretePrototype2"
public class ConcretePrototype2 : Prototype
{
// Rakentaja
public ConcretePrototype2 ( string id ) : base ( id )
{
}
}
}
PHP-esimerkki
PHP lähdekoodi
<?php
/**
* Prototyyppien kelvollisten luokkien hierarkia
*/
abstrakti luokka Maasto {}
abstrakti luokka Meri ulottuu Maasto {}
luokka MaaSea ulottuu Meri { }
luokka MarsSea ulottuu Meri {}
luokka VenusSea ulottuu meri {}
abstrakti luokka tasangot tasangot { } luokka EarthPlains tasangot { } luokka MarsPlains tasangot { } luokka VenusPlains tasangot { }
abstrakti luokka Metsä laajentaa Maastoa {} luokka EarthForest laajentaa metsää {} luokka MarsForest laajentaa metsää {} luokka VenusForest laajentaa metsää {}
/**
* Prototyypin tehdaslogiikan määrittely
*/
luokka TerrainFactory {
yksityinen $meri ;
yksityinen $metsä ;
yksityinen $plains ;
julkinen toiminto __konstrukti ( Meri $meri , Tasangot $tasangot , Metsä $metsä ) {
$this -> meri = $meri ;
$this -> plains = $plains ;
$this -> metsä = $metsä ;
}
function getSea ( ) {
paluu klooni $this -> meri ;
}
function getPlains ( ) {
paluu klooni $this -> plains ;
}
function getForest ( ) {
return klooni $this -> metsä ;
}
}
/**
* Luo tehdas annetuilla prototyyppiparametreilla
*/
$prototypeFactory = new TerrainFactory (
uusi EarthSea (),
uusi MarsPlains (),
uusi VenusForest ()
);
/**
* Luo annetut objektit kloonaamalla
*/
$sea = $prototypeFactory -> getSea ();
$plains = $prototypeFactory -> getPlains ();
$metsä = $prototypeFactory -> getForest ();
Rubiiniesimerkki
Rubyn lähdekoodi
moduulin prototyyppi
# "prototyyppi"
luokan prototyyppi
# Ominaisuus
# id-ominaisuus on alun perin jokaisessa objektissa, joten käytämme ominaisuutta nimi
attr_reader :nimi
#rakentaja
def alusta nimi
@nimi = nimen
loppu
loppu
loppu
# Luo ilmentymä ja kloonaa se
p1 = Prototyyppi :: Prototyyppi . uusi "nimeni" # Prototype-luokan objekti luodaan perinteisellä tavalla - menetelmällä new
p2 = p1 . clone # kloonausmenetelmä on oletuksena jokaisessa objektissa - sitä ei tarvitse määrittää
laittaa "p1.id = #{ p1 . objektin_tunnus } , p2.id = #{ p2 . objektin_tunnus } " # erilaista tunnusta tulostetaan laittaa "p1.name = #{ p1 . name } , p2.name = #{ p2 . nimi } " # identtistä nimeä tulostetaan - "nimeni"
# Odota, että käyttäjä
saa
VB.NET esimerkki
Lähdeteksti VB.NET-kielellä
Nimitilan prototyyppiluokka
MainApp Shared
Sub Main () ' Luo kaksi esiintymää ja kloonaa kumpikin
Himmeä p1 Prototyyppinä = Uusi ConcretePrototype1 ( " I " ) Dim c1 Prototypena = p1 . Kloonaa () -konsoli . WriteLine ( "Klooni: {0}" , c1 . Id )
Dim p2 As Prototype = Uusi ConcretePrototype2 ( "II" )
Dim c2 As Prototype = p2 . Kloonaa ()
-konsoli . WriteLine ( "Klooni: {0}" , c2 . Id )
konsoli . Lue ()
Lopeta Sub
End Class
"Prototyyppi"
MustInherit Class Prototype
Yksityinen m_id merkkijonona _
' Constructor
Public Sub New ( ByVal id As String )
Me . m_id = id
End Sub
'
Julkinen vain luku -ominaisuuden tunnus ( ) merkkijonona Hanki Palautus m_id Loppu Hanki loppuomaisuus
Julkinen MustOverride Function Clone ( ) Prototyypin loppuluokkana _
"ConcretePrototype1"
Luokka ConcretePrototype1
Peri Prototype
' Constructor
Public Sub New ( ByVal id As String )
MyBase . Uusi ( id )
End Sub
Julkinen ohittaa funktion Klooni () Prototyyppinä ' Epätäydellinen kopio Palauta DirectCast ( Me . MemberwiseClone ( ) , Prototyyppi ) Loppufunktion loppuluokka
"ConcretePrototype2"
Luokka ConcretePrototype2
perii prototyypin
Constructor
Public Sub New ( ByVal id As String )
MyBase . Uusi ( id )
End Sub
Julkinen ohittaa funktion Klooni () Prototyyppinä ' Epätäydellinen kopio Palauta DirectCast ( Me . MemberwiseClone ( ) , Prototyyppi ) Loppufunktio End Class End Namespace
Delphi esimerkki
Lähdeteksti Delphissä
ohjelma PrototypePattern ;
{$APPTYPE CONSOLE}
käyttää
SysUtilsia ;
tyyppi
TPrototyyppi = luokka
julkinen
toiminto Klooni : TPrototyyppi ; virtuaalinen ; abstrakti ;
loppu ;
tyyppi
TPrototypeType = luokka ( TPototyyppi )
yksityinen
FID : Kokonaisluku ;
Finfo : String ;
julkinen
omaisuustunnus : Kokonaisluku lue FID kirjoittaa FID ; _ ominaisuus Info : Merkkijono lukea FIinfo kirjoittaa FIinfo ;
toiminto Klooni : TPrototyyppi ; ohittaa ;
loppu ;
toiminto TPrototypeType . Klooni : T Prototyyppi ;
var
vClone : TPrototypeType ;
begin
vClone := TPrototypeType . luoda ;
vClone . ID := ID ;
vClone . Info := Info ;
Tulos := vClone ;
loppu ;
menettely CloneAndShow ( Prototyyppi : TPrototypeType ) ;
var
vClone : TPrototypeType ;
begin
vClone := Prototyyppi . klooni ;
yritä
kirjoittaa ( vClone . ID ) ;
Kirjoita ( vClone.Info ) ; _ _ lopulta vClone . Ilmainen ; loppu ;
WriteLn ;
loppu ;
var
vConcretePrototype1 , vConcretePrototype2 : TPrototypeType ;
begin
vConcretePrototype1 := TPrototypeType . luoda ;
vConcretePrototype2 := TPrototyyppityyppi . luoda ;
kokeile
vConcretePrototype1 . ID := 10 ;
vConcretePrototype1 . Info := 'Prototyyppi1!' ;
vConcretePrototype2 . ID := 11 ;
vConcretePrototype2 . Info := 'Prototyyppi2!' ;
CloneAndShow ( vConcretePrototype1 ) ;
CloneAndShow ( vConcretePrototype2 ) ;
lopuksi
vConcretePrototype1 . Ilmainen ;
vConcretePrototype2 . Ilmainen ;
loppu ;
Readln ;
loppua .
CoffeeScript-esimerkki
CoffeeScript esimerkki
luokan PresidenttiPrototyypin
rakentaja: (@proto) ->
klooni: ->
asiakas = uusi presidentti () asiakas.first
= @proto . ensimmäinen asiakas.viimeinen
= @proto . viimeinen asiakas.aka
= @proto . a.k.a
asiakas
luokan Presidentti
rakentaja: (@first, @last, @aka) ->
sano: -> konsoli . log "Hänen nimensä on #{ @first } #{ @last } eli #{ @aka } ."
run = ->
proto = uusi presidentti ( " Jimmy " , " Wales " , " Jimbo " )
prototyyppi = uusi presidenttiPrototyyppi ( proto )
asiakas = prototyyppi . klooni ()
asiakas . sano ()
juosta ()
Io esimerkki
Io lähdekoodi
Foo := Objektiklooni Foo smth
:= 2 bar : = Foo klooni
Kirjallisuus
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Olio-suunnittelun tekniikat. Suunnittelumallit = Suunnittelumallit: Uudelleenkäytettävän olio-ohjelmiston elementit. - Pietari. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (myös ISBN 5-272-00355-1 )
Katso myös
Linkit