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

ترجمه و تالیف : پشتیبانی راکت
تاریخ انتشار : 13 خرداد 98
خواندن در 1 دقیقه
دسته بندی ها : برنامه نویسی , پی اچ پی

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

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

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

دیزاین پترن سازنده - 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 و …) را صدا بزند
گردآوری و تالیف پشتیبانی راکت
آفلاین
user-avatar

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

دیدگاه‌ها و پرسش‌ها

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