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
prototyp
Sorts alstrande
Beskrivs i Design Patterns Ja

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:

Använd detta designmönster när systemet inte bryr sig om hur produkter skapas, förpackas och presenteras i det:

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 . ( 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 ()
      1. UTGÅNG ###
  1. ['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