**Նախատիպը** նախագծման ստեղծող ձևանմուշ է, որը նոր օբյեկտներ է ստեղծում նախօրոք սահմված նախատիպը պատճենելով։

Ընդհանուր հասկացողություններ
----------------------------

* Client - հայցող
* Instance - նմուշ
* Implementation - իրականացում
* Product - արգասիք

Նկարագրություն
--------------

Նախատիպ ձևանմուշն օգտագործվում է հետևյալ նպատակների համար.

* խուսափում է ենթադասերի ստեղծող օբյեկտների ժառանգումից հայցողի ծրագրային ապահովման մեջ, ինչպես այդ անում է Աբստրակտ ֆաբրիկա ձևանմուշը։
* խուսափում է ստանդարտ ճանապարհով օբյեկտի ստեղծման վրա լրացուցիչ ջանքերից (ի նկատի ունի կոսնտրուկտորի օգտագործումը, քանի որ այս դեպքում նույնպես կկանչվեն կոնստրուկտորներ ողջ հիերարխիայի համար), երբ նրա ծախսած ժամանակը անթույլատրելի թանկ է ծրագրային ապահովվության համար։

Նախագծման այս ձևանմուշը խորհուրդ է տրվում օգտագործել, երբ համակարգը չպետք է կախված լինի նրանից, թե ինչպես են նրանում ստեղծվում, կոմպանավորվում և ներկայացվում արգասիքները.

* ինտանսավորված դասերը բնորոշվում են իրականցման ժամանակ (օրինակ դինամիկ բեռնման օգնությամբ).
* զուգահեռ հիերարխիա ունեցող արգասիքներում դասերի հիերարխիայի կառուցումից կամ ֆաբրիկաներից խուսափելու համար,
* դասերի նմուշները կարող են գտնվել տարբեր վիճակներում։ Կարող է ավելի նպատակահարմար լինի ունենալ համապատասխան թվով նախատիպեր և կլոնավորել դրանք, քան թե դասից ամեն անգամ անհրաժեշտ վիճակով նմուշ ստեղծել։

Կառուցվածք
----------

Նախատիպ ձևանմուշի սխեմանՆախատիպ ձևանմուշի սխեման

Պսեվդոկոդ
---------

```
**class** WordOccurrences **is**
 **field** occurrences **is**
  The list of the index of each occurrence of the word in the text.

 **constructor** WordOccurrences(text, word) **is**
   **input։** the *text* in which the occurrences have to be found
   **input։** the *word* that should appear in the text
  Empty the *occurrences* list
  **for each** textIndex **in** text
   isMatching ։= true
   **for each** wordIndex **in** word
    **if** the current word character does not match the current text character **then**
     isMatching ։= false
   **if** isMatching is true **then**
    Add the current textIndex into the *occurrences* list

 **method** getOneOccurrenceIndex(n) **is**
   **input։** a number to point on the *n*th occurrence.
   **output։** the index of the *n*th occurrence.
  Return the *n*th item of the *occurrences* field if any.

 **method** clone() **is**
   **output։** a WordOccurrences object containing the same data.
  Call clone() on the super class.
  On the returned object, set the *occurrences* field with the value of the local *occurrences* field.
  Return the cloned object.

text ։= "The prototype pattern is a creational design pattern in software development first described in design patterns, the book."
word ։= "pattern"d
searchEngine := new WordOccurrences(text, word)
anotherSearchEngine := searchEngine.clone()
```

*(այս ալգորիթմը օպտիմիզացիայի ենթարկված չէ)*

Օրինակներ
---------

### C++

```
class Meal {
public:
 virtual ~Meal();
 virtual void eat() = 0;
 virtual Meal \*clone() const = 0;
 //...
};
class Spaghetti : public Meal {
public:
 Spaghetti( const Spaghetti &);
 void eat();
 Spaghetti \*clone() const { return new Spaghetti( \*this ); }
 //...
};

```

### Java

```
/\*\*
 \* Prototype Class
 \*/
public class Cookie implements Cloneable {
 
 protected int weight;

 @Override
 public Cookie clone() throws CloneNotSupportedException {
 Cookie copy = new Cookie();
 copy.weight = this.weight;
 
 //In an actual implementation of this pattern you might now change references to
 //the expensive to produce parts from the copies that are held inside the prototype.

 return copy;
 }
}

/\*\*
 \* Concrete Prototypes to clone
 \*/
public class CoconutCookie extends Cookie { }

```

```
/\*\*
 \* Client Class
 \*/
public class CookieMachine {

 private Cookie cookie; // Could have been a private Cloneable cookie.

 public CookieMachine(Cookie cookie) {
 this.cookie = cookie;
 }

 public Cookie makeCookie() throws CloneNotSupportedException {
 return (Cookie) this.cookie.clone();
 }

 public static void main(String args[]) throws CloneNotSupportedException {
 Cookie tempCookie = null;
 Cookie prot = new CoconutCookie();
 CookieMachine cm = new CookieMachine(prot);
 for (int i = 0; i < 100; i++)
 tempCookie = cm.makeCookie();
 }
}

```

### C#

```
 using System;
 
 namespace Prototype
 { 
 class MainApp
 { 
 static void Main()
 {
 // Create two instances and clone each
 
 Prototype p1 = new ConcretePrototype1("I");
 Prototype c1 = p1.Clone();
 Console.WriteLine ("Cloned: {0}", c1.Id);
 
 Prototype p2 = new ConcretePrototype2("II");
 Prototype c2 = p2.Clone();
 Console.WriteLine ("Cloned: {0}", c2.Id);
 
 // Wait for user
 Console.Read();
 }
 }
 
 // "Prototype"
 
 abstract class Prototype
 {
 private string id;
 
 // Constructor
 public Prototype(string id)
 {
 this.id = id;
 }
 
 // Property
 public string Id
 {
 get{ return id; }
 }
 
 public abstract Prototype Clone();
 }
 
 // "ConcretePrototype1"
 
 class ConcretePrototype1 : Prototype
 {
 // Constructor
 public ConcretePrototype1(string id) : base(id)
 {
 }
 
 public override Prototype Clone()
 {
 // Shallow copy
 return (Prototype)this.MemberwiseClone();
 }
 }
 
 // "ConcretePrototype2"
 
 class ConcretePrototype2 : Prototype
 {
 // Constructor
 public ConcretePrototype2(string id) : base(id)
 {
 }
 
 public override Prototype Clone()
 {
 // Shallow copy
 return (Prototype)this.MemberwiseClone();
 }
 }
 }

```

### PHP

```
<?php
/\*\*
 \* Հասանելի դասերի հիերարխիա նախատիպերի ստեղծման համար
 \*/ 
abstract class Terrain {}

abstract class Sea extends Terrain {}
class EarthSea extends Sea {}
class MarsSea extends Sea {}
class VenusSea extends Sea {}

abstract class Plains extends Terrain {}
class EarthPlains extends Plains {}
class MarsPlains extends Plains {}
class VenusPlains extends Plains {}

abstract class Forest extends Terrain {}
class EarthForest extends Forest {}
class MarsForest extends Forest {}
class VenusForest extends Forest {}

/\*\*
 \* Նախատիպի ֆաբրիկայի տրամաբանության որոշում
 \*/
class TerrainFactory {
    private $sea;
    private $forest;
    private $plains;

    public function \_\_construct( Sea $sea, Plains $plains, Forest $forest ) {
        $this->sea = $sea;
        $this->plains = $plains;
        $this->forest = $forest;
    }
    function getSea( ) {
        return clone $this->sea;
    }
    function getPlains( ) {
        return clone $this->plains;
    }
    function getForest( ) {
        return clone $this->forest;
    }
}

/\*\*
 \* Ֆաբրիկայի ստեղծումը ըստ նախատիպի տրված պարամետրերի
 \*/
$prototypeFactory = new TerrainFactory(
new EarthSea(),
new MarsPlains(),
new VenusForest()
);

/\*\*
 \* Տրված օբյեկտների ստեղծումը կլոնավորման միջոցով
 \*/
$sea = $prototypeFactory->getSea();
$plains = $prototypeFactory->getPlains();
$forest = $prototypeFactory->getForest();

```

### Ruby

```
module Prototype

 # "Prototype"
 
 class Prototype
 
 # Property
 # id-ի հատկությունը սկզբում առկա է ամեն օբյեկտի մոտ, դրա համար էլ օգտագործվում է name հատկությունը

 attr\_reader :name

 # Constructor

 def initialize name
 @name = name
 end
 
 end
end
 
# Create an instance and clone it
p1 = Prototype::Prototype.new "my name" # Prototype դասի օբյեկտը ստեղծվում է ավանդական ճանապարհով` new մեթոդով
p2 = p1.clone # clone մեթոդը ի սկզբանե գոյություն ունի բոլոր օբյետկների համար։ Նրան բնորոշել պետք չէ

puts "p1.id = #{p1.id}, p2.id = #{p2.id}" # կտպվեն տարբեր id-ներ
puts "p1.name = #{p1.name}, p2.name = #{p2.name}" # կտպվի միևնույն name-ը- "my name"

# Wait for user
gets

```

### VB.NET

```
Namespace Prototype
 Class MainApp
 Shared Sub Main()
 ' Երկու նախատիպերի ստեղծում և նրանցից յուրաքանչյուրի կլոնավորում

 Dim p1 As Prototype = New ConcretePrototype1("I")
 Dim c1 As Prototype = p1.Clone()
 Console.WriteLine("Cloned: {0}", c1.Id)

 Dim p2 As Prototype = New ConcretePrototype2("II")
 Dim c2 As Prototype = p2.Clone()
 Console.WriteLine("Cloned: {0}", c2.Id)

 Console.Read()
 End Sub
 End Class

 ' "Prototype"

 MustInherit Class Prototype
 Private m\_id As String

 ' Կոնստրուկտոր
 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() As Prototype
 End Class

 ' "ConcretePrototype1"

 Class ConcretePrototype1

 Inherits Prototype
 ' Конструктор
 Public Sub New(ByVal id As String)
 MyBase.New(id)
 End Sub

 Public Overrides Function Clone() As Prototype
 ' Неполная копия
 Return DirectCast(Me.MemberwiseClone(), Prototype)
 End Function
 End Class

 ' "ConcretePrototype2"

 Class ConcretePrototype2
 Inherits Prototype

 ' Конструктор
 Public Sub New(ByVal id As String)
 MyBase.New(id)
 End Sub

 Public Overrides Function Clone() As Prototype
 ' Неполная копия
 Return DirectCast(Me.MemberwiseClone(), Prototype)
 End Function
 End Class
End Namespace

```

### Delphi

```
program PrototypePattern;

{$APPTYPE CONSOLE}

uses
 SysUtils;

type
 TPrototype = class
 public
 function Clone: TPrototype; virtual; abstract;
 end;

type
 TPrototypeType = class(TPrototype)
 private
 FID: Integer;
 FInfo: String;
 public
 property ID: Integer read FID write FID;
 property Info: String read FInfo write FInfo;

 function Clone: TPrototype; override;
 end;

 function TPrototypeType.Clone: TPrototype;
 var
 vClone: TPrototypeType;
 begin
 vClone := TPrototypeType.Create;
 vClone.ID := ID;
 vClone.Info := Info;

 Result := vClone;
 end;

procedure CloneAndShow(Prototype: TPrototypeType);
var
 vClone: TPrototypeType;
begin
 vClone := Prototype.Clone;
 try
 Write(vClone.ID);
 Write(vClone.Info);
 finally
 vClone.Free;
 end;

 WriteLn;
end;

var
 vConcretePrototype1, vConcretePrototype2: TPrototypeType;
begin
 vConcretePrototype1 := TPrototypeType.Create;
 vConcretePrototype2 := TPrototypeType.Create;
 try
 vConcretePrototype1.ID := 10;
 vConcretePrototype1.Info := ' Prototype1!';

 vConcretePrototype2.ID := 11;
 vConcretePrototype2.Info := ' Prototype2!';

 CloneAndShow(vConcretePrototype1);
 CloneAndShow(vConcretePrototype2);
 finally
 vConcretePrototype1.Free;
 vConcretePrototype2.Free;
 end;

 ReadLn;
end.

```

### CoffeeScript

```
class PresidentPrototype
 constructor: (@proto) ->
 clone: ->
 customer = new President()
 customer.first = @proto.first
 customer.last = @proto.last
 customer.aka = @proto.aka
 customer

class President
 constructor: (@first, @last, @aka) ->
 say: -> console.log "His name is #{@first} #{@last} aka #{@aka}."

run = ->
 proto = new President("Jimmy", "Wales", "Jimbo")
 prototype = new PresidentPrototype(proto)
 customer = prototype.clone()
 customer.say()

run()

```

Ծանոթագրություններ
------------------

1. ↑  Design Patterns from the *Gang Of Four*


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * դ
* ք
* խ
Նախագծման ձևանմուշներ |
| --- |
|  |
| ԳօՖիձևանմուշներ | 

|  |  |
| --- | --- |
| Ստեղծող | Աբստրակտ ֆաբրիկա • Կառուցող • Ֆաբրիկային մեթոդ • Նախատիպ • Եզակի օգտագործման |
| Կառուցվածքային | Ադապտեր • Կամուրջ • Կազմող • Դեկորատոր • Ճակատ • Հարմարեցնող • Պրոքսի |
| Վարքագծային | Պարտականությունների շղթա • Հրաման • Թարգմանիչ • Իտերատոր • Միջնորդ • Պահպանող • Դիտորդ • Վիճակ • Մարտավարություն • Կաղապարային մեթոդ • Այցելող |

 |
|  |
| Ստեղծող ձևանմուշներ | Ծույլ բեռնում • Բազմակի օգտագործման • Օբյեկտների ավազան • Ռեսուրսի ստանալը ինիցիալիզացիա է |
|  |
| Կառուցվածքային ձևանմուշներ | Ճակատը հսկող • Մոդուլ |
|  |
| Համաձայնեցման ձևանմուշներ | Ակտիվ օբյեկտ • Հենվող • Մեկուսացում կրկնակի ստուգումով • Ասինքրոն կանչի մեթոդ • Պահպանվող կախոց • Ռեգիստրացնող • Կողպեքավորող • Մոնիտոր • Նախագործող • Ապագործող • Ընթերցողներ-գրողի կողպեք • Պլանավորման • Հոսքերի ավազանի • Հոսքերի լոկալ հիշողություն |
|  |
| Ճարտարապետական ձևանմուշներ | Ճակատը հսկող ձևանմուշ • Զավթող ձևանմուշ • ձևանմուշի ներկայացման վերահսկում • Բազմաշերտ • Հատկորոշում • Հրատարակող-ստորագրող • Մերկ օբյեկտներ • Ծառայության լոկատոր • Ակտիվ գրառման • Բազմության իդենտիֆիկացման • Data access object • Data transfer object |
|  |
| Այլ ձևանմուշներ | Կախվածության ներդնում • Mock օբյեկտ • Զրոյական օբյեկտ • Ծառայող • Թունելային տարատեսակի |

 |