Design Pattern ها
این سند استانداردهای تیم و بهترین شیوهها برای پیادهسازی Design Pattern ها در پروژههای ما را تشریح میکند.
مقدمه
Design Pattern ها راهحلهای اثبات شده برای مشکلات رایج در طراحی نرمافزار هستند. آنها بهترین شیوههایی را نمایندگی میکنند که در طول زمان توسط توسعهدهندگان نرمافزار باتجربه تکامل یافتهاند. این راهنما استانداردهای تیم ما را برای پیادهسازی Design Pattern ها تعیین میکند.
اصول اساسی
1. پیروی از پیادهسازیهای استاندارد
هنگام پیادهسازی هر Design Pattern، به دقت از پیادهسازی استاندارد همانطور که در مرجع رسمی توضیح داده شده، پیروی کنید:
راهنمای Design Pattern های TutorialsPoint
حتی اگر یک Design Pattern خاص را بارها پیادهسازی کردهاید، همیشه به مرجع استاندارد مراجعه کنید. این امر سازگاری در کدبیس را تضمین میکند و از انحراف از Pattern های تثبیت شده جلوگیری میکند.
2. حفظ تعاریف Interface
یکی از رایجترین اشتباهات هنگام پیادهسازی Design Pattern ها، عدم پایبندی به تعاریف استاندارد Interface است. Interface ها اجزای اختیاری نیستند بلکه اجزای ضروری ساختار Pattern هستند.
// ❌ نادرست: Interface غیراستاندارد
interface ProductCreator {
public function makeProduct($type);
}
// ✅ درست: Interface استاندارد Factory Method
interface Creator {
public function factoryMethod(): Product;
}
interface Product {
public function operation(): string;
}
3. اجتناب از پیادهسازیهای خلاقانه
هنگام پیادهسازی Design Pattern ها، از خلاقیت یا "بهبودهای" Pattern استاندارد اجتناب کنید. Pattern ها در طول دههها تصفیه شدهاند و برای موارد استفاده خاص خود بهینهسازی شدهاند.
// ❌ اجتناب: پیادهسازی خلاقانه Singleton
class ImprovedSingleton {
private static $instances = [];
private function __construct() {}
public static function getInstance(string $key = 'default'): self {
if (!isset(self::$instances[$key])) {
self::$instances[$key] = new self();
}
return self::$instances[$key];
}
}
// ✅ درست: پیادهسازی استاندارد Singleton
class Singleton {
private static $instance = null;
private function __construct() {}
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
private function __clone() {}
private function __wakeup() {}
}
4. حفظ انرژی ذهنی
خلاقیت و انرژی ذهنی خود را برای حل مشکلات کسبوکار ذخیره کنید به جای اینکه Design Pattern ها را مجدداً اختراع کنید. پیادهسازیهای استاندارد به خوبی تست شدهاند و توسط سایر توسعهدهندگان قابل درک هستند.
Design Pattern های رایج
در ادامه نمونههایی از پیادهسازیهای استاندارد برای Design Pattern های رایج آمده است. همیشه برای جزئیات کامل به مرجع رسمی مراجعه کنید.
Creational Pattern ها
- Factory Method
- Singleton
- Builder
// Pattern استاندارد Factory Method
// Interface محصول
interface Product {
public function operation(): string;
}
// محصولات مشخص
class ConcreteProductA implements Product {
public function operation(): string {
return "Result of ConcreteProductA";
}
}
class ConcreteProductB implements Product {
public function operation(): string {
return "Result of ConcreteProductB";
}
}
// Interface سازنده
interface Creator {
public function factoryMethod(): Product;
public function someOperation(): string;
}
// سازندگان مشخص
class ConcreteCreatorA implements Creator {
public function factoryMethod(): Product {
return new ConcreteProductA();
}
public function someOperation(): string {
$product = $this->factoryMethod();
return "Creator A: " . $product->operation();
}
}
class ConcreteCreatorB implements Creator {
public function factoryMethod(): Product {
return new ConcreteProductB();
}
public function someOperation(): string {
$product = $this->factoryMethod();
return "Creator B: " . $product->operation();
}
}
// کد کلاینت
function clientCode(Creator $creator) {
echo $creator->someOperation();
}
// استفاده
clientCode(new ConcreteCreatorA());
clientCode(new ConcreteCreatorB());
// Pattern استاندارد Singleton
class Singleton {
private static $instance = null;
// Constructor خصوصی برای جلوگیری از instantiation مستقیم
private function __construct() {}
// متد static که دسترسی به نمونه singleton را کنترل میکند
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// جلوگیری از clone کردن نمونه
private function __clone() {}
// جلوگیری از unserialize کردن نمونه
private function __wakeup() {}
// مثال متد کسبوکار
public function businessLogic() {
// ...
}
}
// استفاده
$singleton = Singleton::getInstance();
$singleton->businessLogic();
// Pattern استاندارد Builder
// محصول
class Product {
private $parts = [];
public function add(string $part): void {
$this->parts[] = $part;
}
public function listParts(): string {
return "Product parts: " . implode(', ', $this->parts);
}
}
// Interface سازنده
interface Builder {
public function reset(): void;
public function buildPartA(): void;
public function buildPartB(): void;
public function buildPartC(): void;
}
// سازنده مشخص
class ConcreteBuilder implements Builder {
private $product;
public function __construct() {
$this->reset();
}
public function reset(): void {
$this->product = new Product();
}
public function buildPartA(): void {
$this->product->add("PartA");
}
public function buildPartB(): void {
$this->product->add("PartB");
}
public function buildPartC(): void {
$this->product->add("PartC");
}
public function getProduct(): Product {
$result = $this->product;
$this->reset();
return $result;
}
}
// مدیر
class Director {
private $builder;
public function setBuilder(Builder $builder): void {
$this->builder = $builder;
}
public function buildMinimalViableProduct(): void {
$this->builder->buildPartA();
}
public function buildFullFeaturedProduct(): void {
$this->builder->buildPartA();
$this->builder->buildPartB();
$this->builder->buildPartC();
}
}
// استفاده
$director = new Director();
$builder = new ConcreteBuilder();
$director->setBuilder($builder);
$director->buildMinimalViableProduct();
$product = $builder->getProduct();
echo $product->listParts();
$director->buildFullFeaturedProduct();
$product = $builder->getProduct();
echo $product->listParts();
Structural Pattern ها
- Adapter
- Decorator
- Proxy
// Pattern استاندارد Adapter
// Interface هدف
interface Target {
public function request(): string;
}
// کلاس موجود با interface ناسازگار
class Adaptee {
public function specificRequest(): string {
return "Specific request from Adaptee";
}
}
// Adapter که Adaptee را با Target سازگار میکند
class Adapter implements Target {
private $adaptee;
public function __construct(Adaptee $adaptee) {
$this->adaptee = $adaptee;
}
public function request(): string {
return "Adapter: (TRANSLATED) " . $this->adaptee->specificRequest();
}
}
// کد کلاینت
function clientCode(Target $target) {
echo $target->request();
}
// استفاده
$adaptee = new Adaptee();
$adapter = new Adapter($adaptee);
clientCode($adapter);
// Pattern استاندارد Decorator
// Interface جزء
interface Component {
public function operation(): string;
}
// جزء مشخص
class ConcreteComponent implements Component {
public function operation(): string {
return "ConcreteComponent";
}
}
// Decorator پایه
abstract class Decorator implements Component {
protected $component;
public function __construct(Component $component) {
$this->component = $component;
}
public function operation(): string {
return $this->component->operation();
}
}
// Decorator های مشخص
class ConcreteDecoratorA extends Decorator {
public function operation(): string {
return "ConcreteDecoratorA(" . parent::operation() . ")";
}
}
class ConcreteDecoratorB extends Decorator {
public function operation(): string {
return "ConcreteDecoratorB(" . parent::operation() . ")";
}
}
// استفاده
$simple = new ConcreteComponent();
$decorator1 = new ConcreteDecoratorA($simple);
$decorator2 = new ConcreteDecoratorB($decorator1);
echo $decorator2->operation();
// خروجی: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
// Pattern استاندارد Proxy
// Interface موضوع
interface Subject {
public function request(): void;
}
// موضوع واقعی
class RealSubject implements Subject {
public function request(): void {
echo "RealSubject: Handling request.\n";
}
}
// Proxy
class Proxy implements Subject {
private $realSubject;
public function __construct(RealSubject $realSubject) {
$this->realSubject = $realSubject;
}
public function request(): void {
if ($this->checkAccess()) {
$this->realSubject->request();
$this->logAccess();
}
}
private function checkAccess(): bool {
echo "Proxy: Checking access prior to firing a real request.\n";
return true;
}
private function logAccess(): void {
echo "Proxy: Logging the time of request.\n";
}
}
// کد کلاینت
function clientCode(Subject $subject) {
$subject->request();
}
// استفاده
$realSubject = new RealSubject();
$proxy = new Proxy($realSubject);
clientCode($proxy);
Behavioral Pattern ها
- Observer
- Strategy
- Template Method
// Pattern استاندارد Observer
// Interface موضوع
interface Subject {
public function attach(Observer $observer): void;
public function detach(Observer $observer): void;
public function notify(): void;
}
// Interface ناظر
interface Observer {
public function update(Subject $subject): void;
}
// موضوع مشخص
class ConcreteSubject implements Subject {
private $state;
private $observers = [];
public function attach(Observer $observer): void {
$this->observers[] = $observer;
}
public function detach(Observer $observer): void {
$key = array_search($observer, $this->observers, true);
if ($key !== false) {
unset($this->observers[$key]);
}
}
public function notify(): void {
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
public function setState($state): void {
$this->state = $state;
$this->notify();
}
public function getState() {
return $this->state;
}
}
// ناظران مشخص
class ConcreteObserverA implements Observer {
public function update(Subject $subject): void {
if ($subject->getState() < 3) {
echo "ConcreteObserverA: Reacted to the event.\n";
}
}
}
class ConcreteObserverB implements Observer {
public function update(Subject $subject): void {
if ($subject->getState() >= 3) {
echo "ConcreteObserverB: Reacted to the event.\n";
}
}
}
// استفاده
$subject = new ConcreteSubject();
$observerA = new ConcreteObserverA();
$subject->attach($observerA);
$observerB = new ConcreteObserverB();
$subject->attach($observerB);
$subject->setState(2);
$subject->setState(5);
$subject->detach($observerB);
$subject->setState(1);
// Pattern استاندارد Strategy
// Interface استراتژی
interface Strategy {
public function doAlgorithm(array $data): array;
}
// استراتژیهای مشخص
class ConcreteStrategyA implements Strategy {
public function doAlgorithm(array $data): array {
sort($data);
return $data;
}
}
class ConcreteStrategyB implements Strategy {
public function doAlgorithm(array $data): array {
rsort($data);
return $data;
}
}
// زمینه
class Context {
private $strategy;
public function __construct(Strategy $strategy) {
$this->strategy = $strategy;
}
public function setStrategy(Strategy $strategy): void {
$this->strategy = $strategy;
}
public function doSomeBusinessLogic(): void {
$data = [1, 5, 2, 4, 3];
$result = $this->strategy->doAlgorithm($data);
echo "Context: Sorted data: " . implode(', ', $result) . "\n";
}
}
// استفاده
$context = new Context(new ConcreteStrategyA());
$context->doSomeBusinessLogic();
$context->setStrategy(new ConcreteStrategyB());
$context->doSomeBusinessLogic();
// Pattern استاندارد Template Method
// کلاس انتزاعی
abstract class AbstractClass {
// متد template
final public function templateMethod(): void {
$this->baseOperation1();
$this->requiredOperation1();
$this->baseOperation2();
$this->hook1();
$this->requiredOperation2();
$this->baseOperation3();
$this->hook2();
}
// این عملیاتها از قبل پیادهسازی شدهاند
protected function baseOperation1(): void {
echo "AbstractClass: I am doing the bulk of the work\n";
}
protected function baseOperation2(): void {
echo "AbstractClass: But I let subclasses override some operations\n";
}
protected function baseOperation3(): void {
echo "AbstractClass: But I am doing the bulk of the work anyway\n";
}
// این عملیاتها باید توسط زیرکلاسها پیادهسازی شوند
abstract protected function requiredOperation1(): void;
abstract protected function requiredOperation2(): void;
// Hook ها میتوانند override شوند اما اجباری نیست
protected function hook1(): void {}
protected function hook2(): void {}
}
// کلاسهای مشخص
class ConcreteClass1 extends AbstractClass {
protected function requiredOperation1(): void {
echo "ConcreteClass1: Implemented Operation1\n";
}
protected function requiredOperation2(): void {
echo "ConcreteClass1: Implemented Operation2\n";
}
protected function hook1(): void {
echo "ConcreteClass1: Overridden Hook1\n";
}
}
class ConcreteClass2 extends AbstractClass {
protected function requiredOperation1(): void {
echo "ConcreteClass2: Implemented Operation1\n";
}
protected function requiredOperation2(): void {
echo "ConcreteClass2: Implemented Operation2\n";
}
protected function hook2(): void {
echo "ConcreteClass2: Overridden Hook2\n";
}
}
// کد کلاینت
function clientCode(AbstractClass $class) {
$class->templateMethod();
}
// استفاده
clientCode(new ConcreteClass1());
clientCode(new ConcreteClass2());
خلاصه
این استانداردها رویکرد تیم ما را برای پیادهسازی Design Pattern ها تعیین میکنند. پیروی از این راهنماییها سازگاری در کدبیس ما را تضمین خواهد کرد:
- همیشه از پیادهسازیهای استاندارد از راهنمای Design Pattern های TutorialsPoint پیروی کنید
- تعاریف Interface را دقیقاً همانطور که در Pattern استاندارد مشخص شده، حفظ کنید
- از پیادهسازیهای خلاقانه یا "بهبودهای" Pattern های استاندارد اجتناب کنید
- انرژی ذهنی را برای حل مشکلات کسبوکار ذخیره کنید به جای اینکه Pattern ها را مجدداً اختراع کنید
راهنمایی CTO تیم:
"Design Pattern ها راهحلهای استانداردشده برای مشکلات رایج هستند. با پیروی از پیادهسازیهای تثبیت شده، اطمینان حاصل میکنیم که کد ما قابل نگهداری و توسط همه اعضای تیم قابل درک است. به یاد داشته باشید که Interface ها اجزای اختیاری نیستند بلکه اجزای ضروری ساختار Pattern هستند."
قانون عملی:
- همیشه هنگام پیادهسازی یک Design Pattern به مرجع استاندارد مراجعه کنید
- پیادهسازیهای Design Pattern را در طول بررسی کد بازبینی کنید تا اطمینان حاصل شود که از استانداردها پیروی میکنند
مطالعه بیشتر: