
原则SOLID是所有开发人员都必须理解的编程标准,以避免创建不良的体系结构。 该标准在OOP中被广泛使用。 如果正确应用,它将使代码更具可扩展性,逻辑性和可读性。 当开发人员在糟糕的体系结构的指导下创建应用程序时,代码变得不灵活,即使很小的更改也可能导致错误。 因此,您必须遵循SOLID的原则。
掌握它们将花费一些时间,但是如果您按照这些原则编写代码,其质量将会提高,并且您将掌握创建一个好的软件体系结构的过程。
要了解SOLID的原理,您需要清楚地了解如何使用界面。 如果您不了解,请先阅读
文档 。
我将以最简单的方式说明SOLID,因此对于初学者来说更容易理解。 我们将一一考虑原则。
单一责任原则
导致班级变更的原因只有一个。
一堂课只能解决一个问题。 它可能有几种方法,但是它们仅应用于解决一般问题。 所有方法和属性都应达到一个目的。 如果一个类有多个目的,则必须将其划分为单独的类。
考虑一个例子:
<?php
namespace Demo;
use DB;
class OrdersReport
{
    public function getOrdersInfo($startDate, $endDate)
    {
        $orders = $this->queryDBForOrders($startDate, $endDate);
        
        return $this->format($orders);
    }
    protected function queryDBForOrders($startDate, $endDate)
    {   // If we would update our persistence layer in the future,
        // we would have to do changes here too. <=> reason to change!
        return DB::table('orders')->whereBetween('created_at', [$startDate, $endDate])->get();
    }
    protected function format($orders)
    {   // If we changed the way we want to format the output,
        // we would have to make changes here. <=> reason to change!
        return '<h1>Orders: ' . $orders . '</h1>';
    }
}
. ? , (, ). .
, , , XML, JSON, HTML ..
:
<?php
namespace Report;
use Report\Repositories\OrdersRepository;
class OrdersReport
{
        protected $repo;
        protected $formatter;
        public function __construct(OrdersRepository $repo, OrdersOutPutInterface $formatter)
        {
                $this->repo = $repo;
                $this->formatter = $formatter;
        }
        public function getOrdersInfo($startDate, $endDate)
        {
                $orders = $this->repo->getOrdersWithDate($startDate, $endDate);
                return $this->formatter->output($orders);
        }
}
namespace Report;
interface OrdersOutPutInterface
{
        public function output($orders);
}
namespace Report;
class HtmlOutput implements OrdersOutPutInterface
{
        public function output($orders)
        {
                return '<h1>Orders: ' . $orders . '</h1>';
        }
}
namespace Report\Repositories;
use DB;
class OrdersRepository
{
    public function getOrdersWithDate($startDate, $endDate)
    {
        return DB::table('orders')->whereBetween('created_at', [$startDate, $endDate])->get();
    }
}
/ (Open-closed Principle)
, .
(, , ) . , .
:
<?php
class Rectangle
{
    public $width;
    public $height;
    public function __construct($width, $height)
    {
        $this->width = $width;
        $this->height = $height;
    }
}
class Circle
{
    public $radius;
    public function __construct($radius)
    {
        $this->radius = $radius;
    }
}
class AreaCalculator
{
    public function calculate($shape)
    {
        if ($shape instanceof Rectangle) {
            $area = $shape->width * $shape->height;
        } else {
            $area = $shape->radius * $shape->radius * pi();
        }
        
        return $area;
    }
}
$circle = new Circle(5);
$rect = new Rectangle(8,5);
$obj = new AreaCalculator();
echo $obj->calculate($circle);
, 
AreaCalculator. /, , .
? :
<?php
interface AreaInterface
{
    public  function calculateArea();
}
class Rectangle implements AreaInterface
{
    public $width;
    public $height;
    public function __construct($width, $height)
    {
        $this->width = $width;
        $this->height = $height;
    }
    public  function calculateArea(){
        $area = $this->height *  $this->width;
        return $area;
    }
}
  
class Circle implements  AreaInterface
{
    public  $radius;
    public function __construct($radius)
    {
        $this->radius = $radius;
    }
    
    public  function calculateArea(){
        $area = $this->radius * $this->radius * pi();
        return $area;
    }
}
class AreaCalculator
{
    public function calculate($shape)
    {
        $area = 0;
        $area = $shape->calculateArea();
        return $area;
    }
}
$circle = new Circle(5);
$obj = new AreaCalculator();
echo $obj->calculate($circle);
, 
AreaCalculator.
(Liskov Substitution Principle)
“Data abstraction” 1987-. 1994- 
:
φ(x) — x T. φ(y) y S, S — T.
, , :
- .
- .
- .
1996- , :
, , , .
: / / .
, () , . , , , , , , . .
:
<?php
interface LessonRepositoryInterface
{
    /**
     * Fetch all records.
     *
     * @return array
     */
    public function getAll();
}
class FileLessonRepository implements LessonRepositoryInterface
{
    public function getAll()
    {
        // return through file system
        return [];
    }
}
class DbLessonRepository implements LessonRepositoryInterface
{
    public function getAll()
    {
        /*
            Violates LSP because:
              - the return type is different
              - the consumer of this subclass and FileLessonRepository won't work identically
         */
        // return Lesson::all();
        // to fix this
        return Lesson::all()->toArray();
    }
}
(Interface Segregation Principle)
, .
, , .
, .
:
<?php
interface workerInterface
{
    public  function work();
    public  function  sleep();
}
class HumanWorker implements workerInterface
{
    public  function work()
    {
        var_dump('works');
    }
    public  function  sleep()
    {
        var_dump('sleep');
    }
}
class RobotWorker implements workerInterface
{
    public  function work()
    {
        var_dump('works');
    }
    public  function sleep()
    {
        // No need
    }
}
RobotWorker’ , 
sleep, . . :
<?php
interface WorkAbleInterface
{
    public  function work();
}
interface SleepAbleInterface
{
    public  function  sleep();
}
class HumanWorker implements WorkAbleInterface, SleepAbleInterface
{
    public  function work()
    {
        var_dump('works');
    }
    
    public  function  sleep()
    {
        var_dump('sleep');
    }
}
class RobotWorker implements WorkAbleInterface
{
    public  function work()
    {
        var_dump('works');
    }
}
(Dependency Inversion Principle)
. .
. .
: , - .
, , , .
:
<?php
class MySQLConnection
{
   /**
   * db connection
   */
   public function connect()
   {
      var_dump('MYSQL Connection');
   }
}
class PasswordReminder
{    
    /**
     * @var MySQLConnection
     */
     private $dbConnection;
     
    public function __construct(MySQLConnection $dbConnection) 
    {
      $this->dbConnection = $dbConnection;
    }
}
, « » « ». .
, , 
MySQLConnection PasswordReminder, 
MySQLConnection. 
PasswordReminder MySQLConnection.
MySQLConnection MongoDBConnection, 
PasswordReminder.
PasswordReminder , - . ? :
<?php
interface ConnectionInterface
{
    public function connect();
}
class DbConnection implements ConnectionInterface
{
    /**
     * db connection
     */
    public function connect()
    {
        var_dump('MYSQL Connection');
    }
}
class PasswordReminder
{
    /**
     * @var ConnectionInterface
     */
    private $dbConnection;
    public  function __construct(ConnectionInterface $dbConnection)
    {
        $this->dbConnection =  $dbConnection;
    }
}
MySQLConnection MongoDBConnection. 
PasswordReminder, 
PasswordReminder .