دیزاین پترن سازنده - Builder
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 3 دقیقه

دیزاین پترن سازنده - Builder

الگوی سازنده یک الگوی مهندسی نرم‌افزار به منظور ایجاد اشیا می باشد. این الگو به منظور حل وجۀ دیگری از مشکل ساخت و تنظیم اشیا در برنامه نویسی معرفی شده است. مشکل بدین شرح است که گاهی نیاز است هنگام ساخت یک شی تعداد زیادی پارامتر را به سازندۀ ( constructor ) آن تحویل دهیم و این کار برنامه نویسی و همچنین خوانایی برنامه را کم می‌کند .

به منظور حل این مشکل از الگوی سازنده استفاده می‌کنیم. در این تکنیک به جای طراحی تعدادی سازنده ( constructor ) با تعداد زیادی پارامتر از یک شی دیگر استفاده می‌کنیم که کار پارامتردهی را به صورت مرحله به مرحله و خوانا تر انجام می دهد و در نهایت از نوع شی مورد نظر یک نمونه با تنظیمات خواسته شده را به ما تحویل می‌دهد.

معمولاً یک طراح در مسیر طراحی٬ ابتدا با الگوی روش کارخانه ( factory method ) شروع می کند سپس به الگوی کارخانه انتزای ( abstract factory ) یا الگوی نمونه ی اولیه ( prototype ) و یا سازنده ( builder ) متوصل می‌شود . معمولاً هنگامی به الگوی سازنده متوصل می‌شویم که در فرایند طراحی به انعطاف پذیری بیشتر نیاز پیدا می‌کنیم.

هدف از  استفاده از این الگو این است که فرایند ساخت ( construction ) یک شی پیچیده را از کد آن شی  object representation )) جدا کنیم.

سازنده ( buillder )

  • یک رابط انتزاعی برای ساخت شی

سازنده ی پیاده سازی شده و واقعی ( concrete builder )

  • یک پیاده سازی از رابط سازنده می‌باشد . یک شی از این نوع می‌تواند به عنوان یک سازنده برای شی مورد نظر عمل کند.

به مثال زیر توجه کنید

public class StreetMap {
	private final Point origin;
	private final Point destination;

	private final Color waterColor;
	private final Color landColor;
	private final Color highTrafficColor;
	private final Color mediumTrafficColor;
	private final Color lowTrafficColor;

	public static class Builder {
		// Required parameters
		private final Point origin;
		private final Point destination;

		// Optional parameters - initialize with default values
		private Color waterColor         = Color.BLUE;
		private Color landColor          = new Color(30, 30, 30);
		private Color highTrafficColor   = Color.RED;
		private Color mediumTrafficColor = Color.YELLOW;
		private Color lowTrafficColor    = Color.GREEN;

		public Builder(Point origin, Point destination) {
			this.origin      = origin;
			this.destination = destination;
		}

		public Builder waterColor(Color color) {
			waterColor = color;
			return this;
		}

		public Builder landColor(Color color) {
			landColor = color;
			return this;
		}

		public Builder highTrafficColor(Color color) {
			highTrafficColor = color;
			return this;
		}

		public Builder mediumTrafficColor(Color color) {
			mediumTrafficColor = color;
			return this;
		}

		public Builder lowTrafficColor(Color color) {
			lowTrafficColor = color;
			return this;
		}

		public StreetMap build() {
			return new StreetMap(this);
		}

	}

	private StreetMap(Builder builder) {
		// Required parameters
		origin      = builder.origin;
		destination = builder.destination;

		// Optional parameters
		waterColor         = builder.waterColor;
		landColor          = builder.landColor;
		highTrafficColor   = builder.highTrafficColor;
		mediumTrafficColor = builder.mediumTrafficColor;
		lowTrafficColor    = builder.lowTrafficColor;
	}

	public static void main(String args[]) {
		StreetMap map = new StreetMap.Builder(new Point(50, 50), new Point(100,
				100)).landColor(Color.GRAY).waterColor(Color.BLUE.brighter())
				.build();
	}
}

کد های بالا با استفاده از الگوی سازنده در زبان جاوا نوشته شده است.

حالا به مثال پایین توجه کنید :

در این مثال 4 کلاس اصلی داریم که متدهای مشترکی دارند  به اصطلاح بهشون product میگیم.

  • EmployedMaleBuilder
  • UnemployedMaleBuilder
  • EmployedFemaleBuilder
  • UnemployedFemaleBuilder

یک کلاس به اسم PersonDirector داریم که وظیفه اجرای متدهای مختلف یک کلاس خاص به ترتیب را دارد .

/**
 * An extremely basic class for creating people objects
 */
class Person
{
    public $employed;

    public $gender;

    const GENDER_MALE   = "Male";

    const GENDER_FEMALE = "Female";

}

/**
 * All people builder should implement this interface
 */
interface PersonBuilderInterface
{
    public function setGender();
    public function setEmployed();
    public function getResult();
}

/**
 * builder to create an employed male
 */
class EmployedMaleBuilder implements PersonBuilderInterface
{
    private $person;

    public function __construct()
    {
        $this->person = new Person();
    }

    public function setGender()
    {
        $this->person->gender = Person::GENDER_MALE;
    }

    public function setEmployed()
    {
        $this->person->employed = true;
    }

    public function getResult()
    {
        return $this->person;
    }
}

/**
 * builder to create an unemployed male
 */
class UnemployedMaleBuilder implements PersonBuilderInterface
{
    private $person;

    public function __construct()
    {
        $this->person = new Person();
    }


    public function setGender()
    {
        $this->person->gender = Person::GENDER_MALE;
    }

    public function setEmployed()
    {
        $this->person->employed = false;
    }

    public function getResult()
    {
        return $this->person;
    }
}

/**
 * builder to create an employed female
 */
class EmployedFemaleBuilder implements PersonBuilderInterface
{
    private $person;

    public function __construct()
    {
        $this->person = new Person();
    }

    public function setGender()
    {
        $this->person->gender = Person::GENDER_FEMALE;
    }

    public function setEmployed()
    {
        $this->person->employed = true;
    }

    public function getResult()
    {
        return $this->person;
    }
}

/**
 * builder to create an unemployed female
 */
class UnemployedFemaleBuilder implements PersonBuilderInterface
{
    private $person;

    public function __construct()
    {
        $this->person = new Person();
    }

    public function setGender()
    {
        $this->person->gender = Person::GENDER_FEMALE;
    }

    public function setEmployed()
    {
        $this->person->employed = false;
    }

    public function getResult()
    {
        return $this->person;
    }
}

/**
 * The director class is part of the builder patter, the build method should be passed a builder.
 * The build method should than call all of the builder methods and return a Person object
 */
class PersonDirector
{
    public function build(PersonBuilderInterface $builder)
    {
        $builder->setGender();
        $builder->setEmployed();

        return $builder->getResult();
    }
}

$director                = new PersonDirector();
$employedMaleBuilder     = new EmployedMaleBuilder();
$unemployedMaleBuilder   = new UnemployedMaleBuilder();
$employedFemaleBuilder   = new EmployedFemaleBuilder();
$unemployedFemaleBuilder = new UnemployedFemaleBuilder();

/**
 * object(Person)#3 (2) {
 * (
 *   ["employed"] => bool(true)
 *   ["gender"] => string(4) "Male"
 * )
 */
$employedMale     = $director->build($employedMaleBuilder);

/**
 * object(Person)#5 (2) {
 * (
 *   ["employed"] => bool(false)
 *   ["gender"] => string(4) "Male"
 * )
 */
$unemployedMale   = $director->build($unemployedMaleBuilder);

/**
 * object(Person)#7 (2) {
 * (
 *   ["employed"] => bool(true)
 *   ["gender"] => string(4) "Female"
 * )
 */
$employedFemale   = $director->build($employedFemaleBuilder);

/**
 * object(Person)#11 (2) {
 * (
 *   ["employed"] => bool(false)
 *   ["gender"] => string(4) "Female"
 * )
 */
$unemployedFemale = $director->build($unemployedFemaleBuilder);

قاعده های دیزاین پترن builder

  • هر builder ای (منظور همان کلاس های  EmployedMaleBuilder و UnemployedMaleBuilder و …) که ایجاد می کنید باید متدهای مختلفی داشته باشند و هر متد آن فقط یه قسمتی از کد یا کانفیگ ما را انجام دهد .
  • هر builder ای (منظور همان کلاس های  EmployedMaleBuilder و UnemployedMaleBuilder و …) که ایجاد می کنید باید از اینترفیس مورد نظر implement شود .
  • هر builder ای (منظور همان کلاس های  EmployedMaleBuilder و UnemployedMaleBuilder و …) که ایجاد می کنید باید یک متد () getResult داشته باشد و تمام آبجکت آماده شده را بازگرداند .
  • به جای اینکه متدهای داخل builder ها را خودمان مستقیم صدا بزنیم باید شی builder را ایجاد کنی و آن را به کلاس director خودمان پاس دهیم تا متدها داخل آن صدا زده شود .
  • هر کلاس کلاس director باید یک متد build داشته باشد تا متدهای داخل کلاس های builder (منظور همان کلاس های  EmployedMaleBuilder و UnemployedMaleBuilder و …) را صدا بزند

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
در انتظار ثبت رای

/@roocketir

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

دیدگاه و پرسش

برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید