Prototyp (designmö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 9 mars 2016; kontroller kräver
11 redigeringar .
Prototyp , ( eng. Prototype ) -genererande designmönster .
Utnämning
Anger vilka typer av objekt som ska skapas med en prototypinstans och skapar nya objekt genom att kopiera denna prototyp. Det låter dig komma bort från implementeringen och låter dig följa principen om "programmering genom gränssnitt". Ett gränssnitt/abstrakt klass högst upp i hierarkin anges som den returnerande typen, och efterkommande klasser kan ersätta en arvtagare som implementerar denna typ där.
Enkelt uttryckt är detta mönstret för att skapa ett objekt genom att klona ett annat objekt istället för att skapa det genom en konstruktor.
Applikation
Mönstret används för att:
- för att undvika ytterligare ansträngningar för att skapa ett objekt på ett standardsätt (vilket betyder användningen av en konstruktor, eftersom i detta fall konstruktörerna för hela hierarkin av objektets förfäder också kommer att kallas), när detta är oöverkomligt dyrt för applikationen.
- undvik att ärva objektskaparen i klientapplikationen, som det abstrakta fabriksmönstret gör .
Använd detta designmönster när systemet inte bryr sig om hur produkter skapas, förpackas och presenteras i det:
- instansierade klasser bestäms vid körning, till exempel genom dynamisk laddning;
- undvika att bygga klasshierarkier eller fabriker parallellt med produktklasshierarkin;
- klassinstanser kan vara i en av flera olika tillstånd. Det kan vara bekvämare att ställa in lämpligt antal prototyper och klona dem, snarare än att manuellt instansiera klassen i lämpligt tillstånd varje gång.
Exempel
Python-exempel
Källkod i Python
#!/usr/bin/env python
# -*- kodning: utf-8 -*-
importera kopia
klass prototyp :
def __init__ ( själv ):
själv . _objekt = {}
def register_object ( själv , namn , obj ):
"""Registrera ett objekt"""
själv . _objekt [ namn ] = obj
def unregister_object ( self , name ):
"""Avregistrera ett objekt"""
del self . _objekt [ namn ]
def clone ( själv , namn , ** attr ):
"""Klona ett registrerat objekt och uppdatera inre attributordbok"""
obj = kopiera . deepcopy ( själv . _objekt . få ( namn ))
obj . __dikt__ . uppdatera ( attr )
returnera obj
klass A :
def __init__ ( själv ):
själv . x = 3
själv . y = 8
själv . z = 15
själv . skräp = [ 38 , 11 , 19 ]
def __str__ ( själv ):
returnera ' {} {} {} {} ' . format ( self . x , self . y , self . z , self . garbage )
def main ():
a = A ()
prototyp = Prototyp ()
prototyp . register_object ( 'objecta' , a )
b = prototyp . klon ( 'objecta' )
c = prototyp . klon ( 'objecta' , x = 1 , y = 2 , skräp = [ 88 , 1 ])
print ([ str ( i ) för i in ( a , b , c )])
if __name__ == '__main__' :
main ()
- UTGÅNG ###
- ['3 8 15 [38, 11, 19]', '3 8 15 [38, 11, 19]', '1 2 15 [88, 1]']
C++ exempel
Källtext i C++
klass måltid {
offentliga :
virtuell ~ måltid ();
virtuell void äta () = 0 ;
virtuell måltid * klon () const = 0 ;
//...
};
klass Spaghetti : offentlig måltid {
offentliga :
Spaghetti ( konst Spaghetti & );
void äta ();
Spaghetti * clone () const { returnera ny Spaghetti ( * this ); }
//...
};
Java-exempel
Java-källa
/**
* Prototyp Klass
*/
offentlig klass Cookie implementerar Klonbar {
skyddad int vikt ;
@Override
public Cookie clone () kastar CloneNotSupportedException {
Cookie copy = ( Cookie ) super . klon ();
//I en faktisk implementering av detta mönster kan du nu ändra referenser till
//det dyra att producera delar från kopiorna som finns inne i prototypen.
returnera kopia ;
}
}
/**
* Konkreta prototyper att klona
*/
offentlig klass CoconutCookie utökar Cookie { }
/**
* Klientklass
*/
offentlig klass CookieMachine {
privat kakkaka ; _ // Kunde ha varit en privat kloningsbar cookie.
public CookieMachine ( Cookie - cookie ) {
detta . kaka = kaka _
}
public Cookie makeCookie () kastar CloneNotSupportedException {
returnera ( Cookie ) detta . kaka . klon ();
}
public static void main ( String args [] ) kastar CloneNotSupportedException {
Cookie tempCookie = null ;
Cookie prot = ny CoconutCookie ();
CookieMachine cm = ny CookieMachine ( prot );
för ( int i = 0 ; i < 100 ; i ++ )
tempCookie = cm . makeCookie ();
}
}
Scala exempel
Scala källkod
package.com _
paketobjekt prototyp { _
class Waffle (
protected var name : String ,
protected var primaryFilling : String ,
protected var specialFilling : Option [ String ] = None
)
utökar Cloneable {
åsidosätt def clone (): Waffle = {
super . klon (). asInstanceOf [ Waffle ]
}
def output () : Enhet = {
println ( s"Waffle $ -namn med primär fyllning $ primaryFilling "
+ ( if ( specialFilling != None ) specialFilling . get else "" ))
}
}
objekt PrototypTest {
def main ( args : Array [ String ]) : Enhet = {
println ( "Output:" )
val chocolateWaffle = new Waffle ( "ChocolateWaffle" , "Chocolate" )
chocolateWaffle . output ()
chokladWaffle . klon (). output ()
val coconutWaffle = new Waffle ( "CoconutWaffle" , "Condensed milk" , Some ( "Coconut" ) ))
coconutWaffle . output ()
coconutWaffle . klon (). output ()
}
}
}
// Utgång:
// VåffelchokladVåffel med
primär fyllning Choklad // VåffelchokladVåffel med primärfyllning Choklad
// Våffla KokosVåffla med primärfyllning Kondenserad mjölkKokos
// Våffla KokosVåffla med primärfyllning Kondenserad mjölkKokosnöt
Exempel i C#
Källtext i C#
använder System ;
namespace Prototype
{
class MainApp
{
static void Main ()
{
// Skapa två instanser och klona varje
Prototype prototype1 = new ConcretePrototype1 ( "I" );
Prototyp clonedPrototype1 = prototyp1 . klon ();
Konsol . WriteLine ( "Clone: {0}" , clonedPrototype1 . Id );
Prototyp prototyp2 = ny ConcretePrototype2 ( "II" );
Prototyp clonedPrototype2 = prototype2 . klon ();
Konsol . WriteLine ( "Klonad: {0}" , clonedPrototype2 . Id );
}
}
// "Prototype"
public abstract class Prototype
{
// Constructor
public Prototype ( string id )
{
this . id = id ;
Konsol . Skriv ( "Baskonstruktorn kallas." );
}
// Property
public string Id { get ; privat set ; }
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-exempel
PHP källkod
<?php
/**
* Hierarki av giltiga klasser för prototyper
*/
abstrakt klass Terräng {}
abstrakt klass Havet sträcker sig Terräng {}
klass EarthSea förlänger Havet {}
klass MarsHavet sträcker sig Hav {}
klass VenusHavet sträcker sig Hav {}
abstrakt klass Plains sträcker sig terräng {}
klass EarthPlains sträcker sig slätter {}
klass MarsPlains sträcker sig slätter {}
klass VenusPlains sträcker sig slätter {}
abstrakt klass Skog förlänger Terräng {}
klass EarthForest förlänger Skog {}
klass MarsForest förlänger Skog {}
klass VenusForest förlänger Skog {}
/**
* Definierar prototyp fabrikslogik
*/
klass TerrainFactory {
privat $sea ;
privat $skog ;
privata $slätter ;
public function __construct ( Hav $sea , Plains $plains , Forest $forest ) {
$this -> sea = $sea ;
$this -> plains = $plains ;
$detta -> skog = $skog ;
}
funktion getSea ( ) {
return clone $this -> sea ;
}
funktion getPlains ( ) {
return clone $this -> plains ;
}
funktion getForest ( ) {
return clone $this -> forest ;
}
}
/**
* Skapa en fabrik med de givna prototypparametrarna
*/
$prototypeFactory = ny TerrainFactory (
ny EarthSea (),
ny MarsPlains (),
ny VenusForest ()
);
/**
* Skapa de givna objekten genom att klona
*/
$sea = $prototypeFactory -> getSea ();
$plains = $prototypeFactory -> getPlains ();
$forest = $prototypeFactory -> getForest ();
Ruby exempel
Ruby källkod
modul Prototyp
# "prototyp"
klass prototyp
# Egenskap
# egenskapen id finns initialt för varje objekt, så vi kommer att använda egenskapen namn
attr_reader :namn
# konstruktör
def initialisera namn
@namn = namnslut
_
slutändan
_
# Skapa en instans och klona den
p1 = Prototyp :: Prototyp . nya "mitt namn" # klassobjektet Prototype skapas på traditionellt sätt - med metoden new
p2 = p1 . clone # klonmetoden finns på varje objekt som standard - den behöver inte definieras
sätter "p1.id = #{ p1 . object_id } , p2.id = #{ p2 . object_id } " # olika id kommer att skrivas ut
sätter "p1.name = #{ p1 . name } , p2.name = #{ p2 . name } " # identiska namn kommer att skrivas ut - "mitt namn"
# Vänta på att användaren
får
VB.NET exempel
Källtext på språket VB.NET
Namnområde Prototyp
Klass MainApp
Shared Sub Main ()
' Skapa två instanser och klona vardera
Dim p1 As Prototype = New ConcretePrototype1 ( "I" )
Dim c1 As Prototype = p1 . Klona ()
konsol . WriteLine ( "Klon: {0}" , c1 . Id )
Dim p2 As Prototype = New ConcretePrototype2 ( "II" )
Dim c2 As Prototype = p2 . Klona ()
konsol . WriteLine ( "Klon:{0}" , c2 . Id )
Konsol . Läs ()
End Sub
End Class
"Prototyp"
MustInherit Class Prototype
Privat m_id Som 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
Public MustOverride Function Clone () Som slutklass
för prototyp
' "ConcretePrototype1"
Klass BetongPrototyp1
Ärver Prototype
' Constructor
Public Sub New ( ByVal id As String )
MyBase . Ny ( id )
End Sub
Offentlig åsidosättning Funktion Klon () Som prototyp
' Ofullständig kopia
Return DirectCast ( Me . MemberwiseClone ( ) , Prototyp )
Slutfunktion Slutklass
' "ConcretePrototype2"
Klass ConcretePrototype2
ärver prototyp
' Constructor
Public Sub New ( ByVal id As String )
MyBase . Ny ( id )
End Sub
Offentlig åsidosättning Funktion Klon () Som prototyp
' Ofullständig
kopia Returnera DirectCast ( Me . MemberwiseClone ( ) , Prototyp )
Slutfunktion Slutklass
Slutnamnområde
Delphi exempel
Källtext i Delphi
program PrototypePattern ;
{$APPTYPE KONSOL}
använder
SysUtils ;
typ
TPrototype = klass
offentlig
funktion Klon : TPrototype ; virtuell ; abstrakt ;
slut ;
typ
TPrototypeType = klass ( TPrototype )
privat
FID : Heltal ;
FInfo : String ;
public
property ID : Heltal läs FID skriv FID ;
egenskap Info : Sträng läs FIinfo skriv FIinfo ;
funktion Klon : TPrototyp ; åsidosätta ;
slut ;
funktion TPrototypeType . Clone : T Prototyp ;
var
vClone : TPrototypeType ;
börja
vClone := TPrototypeType . skapa ;
vClone . ID := ID ;
vClone . Info := Info ;
Resultat := vClone ;
slut ;
procedure CloneAndShow ( Prototyp : TPrototypeType ) ;
var
vClone : TPrototypeType ;
börja
vClone := Prototyp . klon ;
försök att
skriva ( vClone . ID ) ;
Skriv ( vClone.Info ) ; _ _ äntligen vClone . Gratis ; slut ;
WriteLn ;
slut ;
var
vConcretePrototype1 , vConcretePrototype2 : TPrototypeType ;
börja
vConcretePrototype1 := TPrototypeType . skapa ;
vConcretePrototype2 := TPrototypeType . skapa ;
prova
vConcretePrototype1 . ID := 10 ;
vConcretePrototype1 . Info := 'Prototyp1!' ;
vConcretePrototype2 . ID := 11 ;
vConcretePrototype2 . Info := 'Prototyp2!' ;
CloneAndShow ( vConcretePrototype1 ) ;
CloneAndShow ( vConcretePrototype2 ) ;
slutligen
vConcretePrototype1 . Gratis ;
vConcretePrototype2 . Gratis ;
slut ;
Läsln ;
slut .
CoffeeScript-exempel
CoffeeScript exempel
klass PresidentPrototypkonstruktör
: (@proto) ->
klon: ->
kund = ny president ()
customer.first = @proto . första kund.sista
= @proto . sista kund.aka
= @proto . a.k. en
kund
klass President
konstruktör: (@first, @last, @aka) ->
säg: -> konsol . log "Hans namn är #{ @first } #{ @last } aka #{ @aka } ."
run = ->
proto = ny president ( "Jimmy" , "Wales" , "Jimbo" )
prototyp = ny presidentPrototyp ( proto )
kund = prototyp . clone ()
kund . säg ()
springa ()
Io exempel
Io källkod
Foo := Objekt klon
Foo smth := 2
Bar := Foo klon
Litteratur
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Tekniker för objektorienterad design. Designmönster = Designmönster: Element av återanvändbar objektorienterad programvara. - St Petersburg. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (även ISBN 5-272-00355-1 )
Se även
Länkar