الگوی نمونه اولیه

الگوی نمونه اولیه یکی از الگوهای طراحی در توسعه نرم‌افزار است. وقتی نوع اشیاء ساخته شونده با یک نمونه اولیه مشخص شود، از این الگو استفاده شده‌است؛ که در واقع یک مورد مشابه از خود ساخته است یا به اصطلاح خودسازی کرده‌است. موارد استفاده از این الگو:
 جلوگیری از وجود کلاس فرزند از یک کلاس سازنده اشیاء در نرم‌افزار مشتری همان طوری که الگوی کارخانه انتزاعی عمل می‌کند.
 جلوگیی از هزینه وراثتی ساخت شیء جدید در روش معمول آن (به عنوان مثال با استفاده از دستور 'new') چرا که در برنامه‌ها این کار از نظر پردازشی پرهزینه خواهد بود.
برای پیاده‌سازی الگو، یک کلاس پایه انتزاعی که یک تابع مجازی خودسازنده ('clone') دارد در نظر می‌گیریم. هر کلاسی که قابلیت ساخت اشاء جدید را داشته باشد از کلاس اولیه ارث برده و دستور خودسازی ('clone') را می‌سازد.

مشتری به جای نوشتن کدی که فراخوانی ساخت شی جدید ('new') را اجرا می‌کند، دستور خودسازی ('clone') را از نمونه اولیه فراخوانی می‌کند. یا یککارخانه را با یک پارامتر تعیین‌کننده نوع کلاس مشتق شونده صدا می‌کند یا دستور خودسازی را از یک سری روش‌های به وجود آمده در یک الگوی طراحی دیگر اجرا می‌کند.

اینتقسیم میتوزی سلولی — که باعث ایجاد دو سلول مشابه می‌شود — یک مثال از یک نمونه اولیه است که از خود تکثیر می‌کند و همان مدل اولیه را به همه ارائه می‌دهد. هنگامی که یک سلول تجزیه می‌شود دو تا از سلول مورد نظر ایجاد می‌شود. به عبارت دیگر کلاس نمونه کلاسی مشابه خود (سلول مشابه خود) ایجاد می‌کند.

ساختار

قوانین کلی 
گاهی الگوهای ساخته شونده تداخل دارند. موارد وجود دارد که هر دو الگوی نمونه اولیه یا کارخانه انتزاعی مناسب خواهد بود. در موارد دیگری کامل‌کننده یکدیگر هستند: کارخانه انتزاعی ممکن است مجموعه‌ای از نمونه‌های را نگه دارد و تا نمونه‌های جدید را از آن‌ها بسازد. الگوی کارخانه انتزاعی، الگوی سازنده، و الگوی نمونه اولیه همگی می‌توانند از الگوی یگانه (singltone) در پیاده‌سازی خود استفاده کنند. کلاس‌های کارخانه انتزاعی اغلب با دستور کارخانه ساخته می‌شوند (ایجاد از طریق ارث بری) اما آن‌ها را می‌توان با استفاده از نمونه اولیه نیز ایجاد کرد (ایجاد از طریق هیئت).

نمونه اولیه به کلاس‌های فرزند نیاز ندارد، ولی به یک مقداردهی اولیه نیاز دارد. بر عکس آن روش کارخانه به مقداردهی اولیه نیاز ندارد ولی به ساخت کلاس‌های فرزند و وراثت نیاز دارد.

طراحی‌هایی که استفاده زیادی از الگوی مرکب (composite) و الگوی طراحی کننده (decorator) می‌کنند، اغلب می‌توانند استفاده‌های خوبی از الگوی نمونه اولیه ببرند.

قاعده کلی می‌تواند این باشد که شما نیاز به خودسازی یک شیء دارید که می‌خواهید در حین اجرا، شیء دیگری با همان مشخصات شیء اولیه تولید کنید. در عمل تمامی پارامترها و مشخصات شیء جدید با شیء اولیه یکسان خواهد بود. اما اگر از ساخت شیء جدید استفاده کنید تمامی پارامترها و مشخصات در حالت اولیه خود خواهند بود. برای مثال، اگر شما در حال طراحی یک سیستم برای انجام محاسبات بانکی می‌خواهید، پس یک کپی از شیءای را نیاز خواهید داشت که اطلاعات حساب شما را در خود دارد، تا تراکنش را در آن انجام دهید، و سپس شیء تغییر داده شده را جایگزین شیء اولیه کنید. در چنین مواردی، بهتر است به جای ساخت شیء جدید از خودسازی استفاده کنید.

شبه کد 
بیایید تا یک جستجوگر تکرار کلمات در متن بسازیم. این کلاس تمام تکرارهای موجود در متن را لیست خواهد کرد. این اشیاء از نظر پردازشی پرهزینه خواهند بود چرا که هزینه شناسایی تکرارها زیاد خواهد بود. پس برای تکرار شدن این شیء، از الگوی نمونه اولیه استفاده می‌کنیم.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 nth occurrence.
      output: the index of the nth occurrence.
    Return the nth 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 
این الگو با استفاده از نمونه اولیه خود انواع اشیاء را می‌سازد. به زبان دیگر، وقتی از نمونه اولیه شیء جدیدی ساخته شود، کلاس اولیه در واقع یک خودساخته از خود را می‌سازد و آن را به عنوان یک یک نمونه اولیه بازمی‌گرداند. در اینجا از تابع MemberwiseClone برای ساخته خودساخته استفاده کرده‌ایم.public abstract class Prototype
{
    // normal implementation
    public abstract Prototype Clone();
}

public class ConcretePrototype1 : Prototype
{
    public override Prototype Clone()
    {
        return (Prototype)this.MemberwiseClone(); // Clones the concrete class.
    }
}

public class ConcretePrototype2 : Prototype
{
    public override Prototype Clone()
    {
        return (Prototype)this.MemberwiseClone(); // Clones the concrete class.
    }
}

مثال Java 
این الگو با استفاده از نمونه اولیه خود انواع اشیاء را می‌سازد. به زبان دیگر، وقتی از نمونه اولیه شیء جدیدی ساخته شود، کلاس اولیه در واقع یک خودساخته از خود را می‌سازد و آن را به عنوان یک یک نمونه اولیه بازمی‌گرداند. در اینجا از تابع Clone برای ساخته خودساخته استفاده کرده‌ایم.
// Prototype pattern

 public abstract class Prototype implements Cloneable {
 public Prototype clone() throws CloneNotSupportedException{
 return (Prototype) super.clone();
}
}

 public class ConcretePrototype1 extends Prototype {
@Override
 public Prototype clone() throws CloneNotSupportedException {
return super.clone();
}
}

public class ConcretePrototype2 extends Prototype {
@Override
public Prototype clone() throws CloneNotSupportedException {
return super.clone();
}
}

مثال PHP 
// The Prototype pattern in PHP is done with the use of built-in PHP function __clone()

abstract class Prototype
{
    public $a;
    public $b;

    public function displayCONS()
    {
        echo "CONS: {$this->a}\n";
        echo "CONS: {$this->b}\n";
    }

    public function displayCLON()
    {
        echo "CLON: {$this->a}\n";
        echo "CLON: {$this->b}\n";
    }

    abstract function __clone();
}

class ConcretePrototype1 extends Prototype
{
    public function __construct()
    {
        $this->a = "A1";
        $this->b = "B1";

        $this->displayCONS();
    }

    function __clone()
    {
        $this->displayCLON();
    }
}

class ConcretePrototype2 extends Prototype
{
    public function __construct()
    {
        $this->a = "A2";
        $this->b = "B2";

        $this->displayCONS();
    }

    function __clone()
    {
        $this->a = $this->a ."-C";
        $this->b = $this->b ."-C";

        $this->displayCLON();
    }
}

$cP1 = new ConcretePrototype1();
$cP2 = new ConcretePrototype2();
$cP2C = clone $cP2;

// RESULT: #quanton81

// CONS: A1
// CONS: B1
// CONS: A2
// CONS: B2
// CLON: A2-C
// CLON: B2-C

جستارهای وابسته 
 الگوهای طراحی
 الگوی کارخانه انتزاعی
 الگوی یگانه
 الگوی سازنده

پانویس

منابع 
 

الگوهای طراحی نرم‌افزار
ویکی‌سازی رباتیک