
原则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
.