Նախատիպ (նախագծման ձևանմուշ)

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

## Ընդհանուր հասկացողություններ
* 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++

```cpp
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

```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 { }
```


```java
/**
 * 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#

```csharp
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
<?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

```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

```vbnet
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

```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

```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()
```


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

Կատեգորիա:Ծրագրավորում