Github: sohelamin, appzcoder
Twitter: sohel_amin
Email: sohelamincse at gmail dot com
Design patterns are solutions to recurring problems, guidelines on how to tackle certain problems.
In other words, It is a description or template for how to solve a problem.
1. Creational Design Patterns
These patterns deal with object creation mechanisms.
2. Structural Design Patterns
These design patterns concern class and object composition.
3. Behavioral Design Patterns
These patterns describe interactions between objects and focus on how objects communicate with each other.
Facade pattern provides a simplified interface to a complex subsystem.
class Cart
{
public function addProducts($products)
{
// Product adding codes goes here
}
public function getProducts()
{
// Product retrieval codes goes here
}
}
class Order
{
public function process($products)
{
// Order processing codes goes here
}
}
class Payment
{
public function charge($charge)
{
// Additional charge codes goes here
}
public function makePayment()
{
// Payment method verify & payment codes goes here
}
}
class Shipping
{
public function calculateCharge()
{
// Calculation codes goes here
}
public function shipProducts()
{
// Ship process codes goes here
}
}
class CustomerFacade
{
public function __construct()
{
$this->cart = new Cart;
$this->order = new Order;
$this->payment = new Payment;
$this->shipping = new Shipping;
}
public function addToCart($products)
{
$this->cart->addProducts($products);
}
public function checkout()
{
$products = $this->cart->getProducts();
$this->totalAmount = $this->order->process($products);
}
public function makePayment()
{
$charge = $this->shipping->calculateCharge();
$this->payment->charge($charge);
$isCompleted = $this->payment->makePayment();
if ($isCompleted) {
$this->shipping->shipProducts();
}
}
}
$customer = new CustomerFacade;
$products = [
[
'name' => 'Polo T-Shirt',
'price' => 40,
],
[
'name' => 'Smart Watch',
'price' => 400,
],
];
$customer->addToCart($products);
$customer->checkout();
$customer->makePayment();
Example: Config, Input, URL, Route, View, DB etc
return [
'aliases' => [
'DB' => Illuminate\Support\Facades\DB::class,
]
]
Step1. Open the config file config/app.php
// become
DB::select();
<?php
namespace Illuminate\Support\Facades;
/**
* @see \Illuminate\Database\DatabaseManager
* @see \Illuminate\Database\Connection
*/
class DB extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'db';
}
}
Step2. Let's open Illuminate\Support\Facades\DB.php
protected function registerConnectionServices()
{
$this->app->singleton('db', function ($app) {
return new DatabaseManager($app, $app['db.factory']);
});
}
Step3. Let's open Illuminate/Database/DatabaseServiceProvider.php
public function __call($method, $parameters)
{
return $this->connection()->$method(...$parameters);
}
Step4. Let's open Illuminate/Database/DatabaseManager.php
// become
$app['db']
class_alias('Illuminate\Support\Facades\DB', 'DB');
// we can call DB instead of Illuminate\Support\Facades\DB now
// vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php
abstract class Facade
{
public static function __callStatic($method, $args)
{
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return $instance->$method(...$args);
}
}
DB::select()
The Repository pattern is usually used to create an interface between business logic & database access layers of an application
// app/Repositories/PostRepositoryInterface.php
<?php
namespace App\Repositories;
interface PostRepositoryInterface
{
public function getAll();
public function find($id);
}
// app/Repositories/PostEloquentRepository.php
<?php
namespace App\Repositories;
use App\Post;
class PostEloquentRepository implements PostRepositoryInterface
{
public function getAll()
{
return Post::all();
}
public function find($id)
{
return Post::findOrFail($id);
}
}
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->bind(
'App\Repositories\PostRepositoryInterface',
'App\Repositories\PostEloquentRepository'
);
}
// app/Http/Controllers/Admin/PostsController.php
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Repositories\PostRepositoryInterface;
class PostsController extends Controller
{
protected $postRepository;
public function __construct(PostRepositoryInterface $postRepository)
{
$this->postRepository = $postRepository;
}
public function index()
{
$posts = $this->postRepository->getAll();
return view('admin.posts.index', compact('posts'));
}
}
The Provider pattern was formulated by Microsoft. It is a mid layer between an API class and the Business Logic/Data Abstraction Layer of the application.
// vendor/laravel/framework/src/Illuminate/Redis/RedisServiceProvider.php
<?php
namespace Illuminate\Redis;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;
class RedisServiceProvider extends ServiceProvider
{
protected $defer = true;
public function register()
{
$this->app->singleton('redis', function ($app) {
$config = $app->make('config')->get('database.redis');
return new RedisManager(Arr::pull($config, 'client', 'predis'), $config);
});
$this->app->bind('redis.connection', function ($app) {
return $app['redis']->connection();
});
}
public function provides()
{
return ['redis', 'redis.connection'];
}
}
// config/app.php
<?php
return [
'providers' => [
Illuminate\Redis\RedisServiceProvider::class,
],
'aliases' => [
'Redis' => Illuminate\Support\Facades\Redis::class,
]
]