Главная страница

Патерны программирования. DesignPatternsphp documentation


Скачать 1.98 Mb.
НазваниеDesignPatternsphp documentation
АнкорПатерны программирования
Дата06.02.2023
Размер1.98 Mb.
Формат файлаpdf
Имя файлаdesignpatternsphp-readthedocs-io-ru-latest.pdf
ТипДокументы
#923605
страница3 из 9
1   2   3   4   5   6   7   8   9
Код
Вы можете найти этот код на
GitHub
Facade.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Facade;
6 7
class
Facade
8
{
9
public function
__construct
(
private
Bios
$bios
,
private
OperatingSystem
$os
)
(continues on next page)
1.2. Структурные шаблоны проектирования (Structural)
59

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
10
{
11
}
12 13
public function turnOn
()
14
{
15
$this
->
bios
->
execute
();
16
$this
->
bios
->
waitForKeyPress
();
17
$this
->
bios
->
launch
(
$this
->
os
);
18
}
19 20
public function turnOff
()
21
{
22
$this
->
os
->
halt
();
23
$this
->
bios
->
powerDown
();
24
}
25
}
OperatingSystem.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Facade;
6 7
interface
OperatingSystem
8
{
9
public function halt
();
10 11
public function getName
()
:
string;
12
}
Bios.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Facade;
6 7
interface
Bios
8
{
9
public function execute
();
10 11
public function waitForKeyPress
();
12 13
public function launch
(OperatingSystem
$os
);
14 15
public function powerDown
();
16
}
60
Глава 1. Паттерны

DesignPatternsPHP Documentation, Выпуск 1.0
Тест
Tests/FacadeTest.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Facade\Tests;
6 7
use
DesignPatterns\Structural\Facade\Bios;
8
use
DesignPatterns\Structural\Facade\Facade;
9
use
DesignPatterns\Structural\Facade\OperatingSystem;
10
use
PHPUnit\Framework\TestCase;
11 12
class
FacadeTest extends
TestCase
13
{
14
public function testComputerOn
()
15
{
16
$os
=
$this
->
createMock
(OperatingSystem
::
class
);
17 18
$os
->
method
(
'getName'
)
19
->
will
(
$this
->
returnValue
(
'Linux'
));
20 21
$bios
=
$this
->
createMock
(Bios
::
class
);
22 23
$bios
->
method
(
'launch'
)
24
->
with
(
$os
);
25 26
/** @noinspection PhpParamsInspection */
27
$facade
=
new
Facade(
$bios
,
$os
);
28
$facade
->
turnOn
();
29 30
$this
->
assertSame
(
'Linux'
,
$os
->
getName
());
31
}
32
}
1.2.8 Текучий Интерфейс (Fluent Interface)
Назначение
Писать код, который легко читается, как предложения в естественном языке (вроде русского или английского).
1.2. Структурные шаблоны проектирования (Structural)
61

DesignPatternsPHP Documentation, Выпуск 1.0
Примеры
• Doctrine2’s QueryBuilder работает примерно также, как пример ниже.
• PHPUnit использует текучий интерфейс, чтобы создавать макеты объектов.
Диаграмма UML
Код
Вы можете найти этот код на
GitHub
Sql.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\FluentInterface;
6 7
class
Sql implements
\Stringable
8
{
9
private array
$fields
=
[];
(continues on next page)
62
Глава 1. Паттерны

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
10
private array
$from
=
[];
11
private array
$where
=
[];
12 13
public function select
(
array
$fields
)
:
Sql
14
{
15
$this
->
fields
=
$fields
;
16 17
return
$this
;
18
}
19 20
public function from
(string
$table
, string
$alias
)
:
Sql
21
{
22
$this
->
from
[]
=
$table
' AS '
$alias
;
23 24
return
$this
;
25
}
26 27
public function where
(string
$condition
)
:
Sql
28
{
29
$this
->
where
[]
=
$condition
;
30 31
return
$this
;
32
}
33 34
public function
__toString
()
:
string
35
{
36
return sprintf
(
37
'SELECT %s FROM %s WHERE %s'
,
38
join
(
', '
,
$this
->
fields
),
39
join
(
', '
,
$this
->
from
),
40
join
(
' AND '
,
$this
->
where
)
41
);
42
}
43
}
Тест
Tests/FluentInterfaceTest.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\FluentInterface\Tests;
6 7
use
DesignPatterns\Structural\FluentInterface\Sql;
8
use
PHPUnit\Framework\TestCase;
9 10
class
FluentInterfaceTest extends
TestCase
11
{
12
public function testBuildSQL
()
(continues on next page)
1.2. Структурные шаблоны проектирования (Structural)
63

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
13
{
14
$query
=
(
new
Sql())
15
->
select
([
'foo'
,
'bar'
])
16
->
from
(
'foobar'
,
'f'
)
17
->
where
(
'f.bar = ?'
);
18 19
$this
->
assertSame
(
'SELECT foo, bar FROM foobar AS f WHERE f.bar = ?'
, (string)
˓→
$query
);
20
}
21
}
1.2.9 Приспособленец (Flyweight)
Назначение
Для уменьшения использования памяти Приспособленец разделяет как можно больше памяти между аналогичными объектами. Это необходимо, когда используется большое количество объектов, состо- яние которых не сильно отличается. Обычной практикой является хранение состояния во внешних структурах и передавать их в объект-приспособленец, когда необходимо.
64
Глава 1. Паттерны

DesignPatternsPHP Documentation, Выпуск 1.0
Диаграмма UML
Код
Вы можете найти этот код на
GitHub
Text.php
1
2 3
declare
(strict_types
=
1
);
4
(continues on next page)
1.2. Структурные шаблоны проектирования (Structural)
65

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
5
namespace
DesignPatterns\Structural\Flyweight;
6 7
/**
8
* This is the interface that all flyweights need to implement
9
*/
10
interface
Text
11
{
12
public function render
(string
$extrinsicState
)
:
string;
13
}
Word.php
1
2 3
namespace
DesignPatterns\Structural\Flyweight;
4 5
class
Word implements
Text
6
{
7
public function
__construct
(
private string
$name
)
8
{
9
}
10 11
public function render
(string
$extrinsicState
)
:
string
12
{
13
return sprintf
(
'Word %s with font %s'
,
$this
->
name
,
$extrinsicState
);
14
}
15
}
Character.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Flyweight;
6 7
/**
8
* Implements the flyweight interface and adds storage for intrinsic state, if any.
9
* Instances of concrete flyweights are shared by means of a factory.
10
*/
11
class
Character implements
Text
12
{
13
/**
14
* Any state stored by the concrete flyweight must be independent of its context.
15
* For flyweights representing characters, this is usually the corresponding

˓→
character code.
16
*/
17
public function
__construct
(
private string
$name
)
18
{
19
}
20 21
public function render
(string
$extrinsicState
)
:
string
(continues on next page)
66
Глава 1. Паттерны

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
22
{
23
// Clients supply the context-dependent information that the flyweight needs to

˓→
draw itself
24
// For flyweights representing characters, extrinsic state usually contains e.g.
˓→
the font.
25 26
return sprintf
(
'Character %s with font %s'
,
$this
->
name
,
$extrinsicState
);
27
}
28
}
TextFactory.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Flyweight;
6 7
use
Countable;
8 9
/**
10
* A factory manages shared flyweights. Clients should not instantiate them directly,
11
* but let the factory take care of returning existing objects or creating new ones.
12
*/
13
class
TextFactory implements
Countable
14
{
15
/**
16
* @var Text[]
17
*/
18
private array
$charPool
=
[];
19 20
public function get
(string
$name
)
:
Text
21
{
22
if
(
!
isset
(
$this
->
charPool
[
$name
])) {
23
$this
->
charPool
[
$name
]
=
$this
->
create
(
$name
);
24
}
25 26
return
$this
->
charPool
[
$name
];
27
}
28 29
private function create
(string
$name
)
:
Text
30
{
31
if
(
strlen
(
$name
)
==
1
) {
32
return new
Character(
$name
);
33
}
34
return new
Word(
$name
);
35
}
36 37
public function count
()
:
int
38
{
39
return count
(
$this
->
charPool
);
40
}
(continues on next page)
1.2. Структурные шаблоны проектирования (Structural)
67

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
41
}
Тест
Tests/FlyweightTest.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Flyweight\Tests;
6 7
use
DesignPatterns\Structural\Flyweight\TextFactory;
8
use
PHPUnit\Framework\TestCase;
9 10
class
FlyweightTest extends
TestCase
11
{
12
private array
$characters
=
[
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
,
'g'
,
'h'
,
'i'
,
'j'
,
'k'
,
13
'l'
,
'm'
,
'n'
,
'o'
,
'p'
,
'q'
,
'r'
,
's'
,
't'
,
'u'
,
'v'
,
'w'
,
'x'
,
'y'
,
'z'
];
14 15
private array
$fonts
=
[
'Arial'
,
'Times New Roman'
,
'Verdana'
,
'Helvetica'
];
16 17
public function testFlyweight
()
18
{
19
$factory
=
new
TextFactory();
20 21
for
(
$i
=
0
;
$i
<=
10
;
$i
++
) {
22
foreach
(
$this
->
characters as
$char
) {
23
foreach
(
$this
->
fonts as
$font
) {
24
$flyweight
=
$factory
->
get
(
$char
);
25
$rendered
=
$flyweight
->
render
(
$font
);
26 27
$this
->
assertSame
(
sprintf
(
'Character %s with font %s'
,
$char
,
$font
),
˓→
$rendered
);
28
}
29
}
30
}
31 32
foreach
(
$this
->
fonts as
$word
) {
33
$flyweight
=
$factory
->
get
(
$word
);
34
$rendered
=
$flyweight
->
render
(
'foobar'
);
35 36
$this
->
assertSame
(
sprintf
(
'Word %s with font foobar'
,
$word
),
$rendered
);
37
}
38 39
// Flyweight pattern ensures that instances are shared
40
// instead of having hundreds of thousands of individual objects
41
// there must be one instance for every char that has been reused for displaying

˓→
in different fonts
42
$this
->
assertCount
(
count
(
$this
->
characters
)
+
count
(
$this
->
fonts
),
$factory
);
43
}
(continues on next page)
68
Глава 1. Паттерны

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
44
}
1.2.10 Прокси (Proxy)
Назначение
Создать интерфейс взаимодействия с любым классом, который трудно или невозможно использовать в оригинальном виде.
Примеры
• Doctrine2 использует прокси для реализации магии фреймворка (например, для ленивой иници- ализации), в то время как пользователь работает со своими собственными классами сущностей и никогда не будет использовать прокси.
1.2. Структурные шаблоны проектирования (Structural)
69

DesignPatternsPHP Documentation, Выпуск 1.0
Диаграмма UML
70
Глава 1. Паттерны

DesignPatternsPHP Documentation, Выпуск 1.0
Код
Вы можете найти этот код на
GitHub
BankAccount.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Proxy;
6 7
interface
BankAccount
8
{
9
public function deposit
(int
$amount
);
10 11
public function getBalance
()
:
int;
12
}
HeavyBankAccount.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Proxy;
6 7
class
HeavyBankAccount implements
BankAccount
8
{
9
/**
10
* @var int[]
11
*/
12
private array
$transactions
=
[];
13 14
public function deposit
(int
$amount
)
15
{
16
$this
->
transactions
[]
=
$amount
;
17
}
18 19
public function getBalance
()
:
int
20
{
21
// this is the heavy part, imagine all the transactions even from
22
// years and decades ago must be fetched from a database or web service
23
// and the balance must be calculated from it
24 25
return array_sum
(
$this
->
transactions
);
26
}
27
}
BankAccountProxy.php
1
2 3
declare
(strict_types
=
1
);
(continues on next page)
1.2. Структурные шаблоны проектирования (Structural)
71

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
4 5
namespace
DesignPatterns\Structural\Proxy;
6 7
class
BankAccountProxy extends
HeavyBankAccount implements
BankAccount
8
{
9
private
?
int
$balance
=
null
;
10 11
public function getBalance
()
:
int
12
{
13
// because calculating balance is so expensive,
14
// the usage of BankAccount::getBalance() is delayed until it really is needed
15
// and will not be calculated again for this instance
16 17
if
(
$this
->
balance
===
null
) {
18
$this
->
balance
=
parent
::
getBalance
();
19
}
20 21
return
$this
->
balance
;
22
}
23
}
Тест
ProxyTest.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Proxy\Tests;
6 7
use
DesignPatterns\Structural\Proxy\BankAccountProxy;
8
use
PHPUnit\Framework\TestCase;
9 10
class
ProxyTest extends
TestCase
11
{
12
public function testProxyWillOnlyExecuteExpensiveGetBalanceOnce
()
13
{
14
$bankAccount
=
new
BankAccountProxy();
15
$bankAccount
->
deposit
(
30
);
16 17
// this time balance is being calculated
18
$this
->
assertSame
(
30
,
$bankAccount
->
getBalance
());
19 20
// inheritance allows for BankAccountProxy to behave to an outsider exactly like

˓→
ServerBankAccount
21
$bankAccount
->
deposit
(
50
);
22 23
// this time the previously calculated balance is returned again without re-
˓→
calculating it
24
$this
->
assertSame
(
30
,
$bankAccount
->
getBalance
());
(continues on next page)
72
Глава 1. Паттерны

DesignPatternsPHP Documentation, Выпуск 1.0
(продолжение с предыдущей страницы)
25
}
26
}
1.2.11 Реестр (Registry)
Назначение
Для реализации централизованного хранения объектов, часто используемых во всем приложении, как правило, реализуется с помощью абстрактного класса только c статическими методами (или с помо- щью шаблона Singleton). Помните, что это вводит глобальное состояние, которого следует избегать.
Используйте Dependency Injection вместо Registry.
Диаграмма UML
1.2. Структурные шаблоны проектирования (Structural)
73

DesignPatternsPHP Documentation, Выпуск 1.0
Код
Вы можете найти этот код на
GitHub
Registry.php
1
2 3
declare
(strict_types
=
1
);
4 5
namespace
DesignPatterns\Structural\Registry;
6 7
use
InvalidArgumentException;
8 9
abstract class
Registry
10
{
11
public const
LOGGER
=
'logger'
;
12 13
/**
14
* this introduces global state in your application which can not be mocked up for

˓→
testing
15
* and is therefor considered an anti-pattern! Use dependency injection instead!
16
*
17
* @var Service[]
18
*/
19
private static array
$services
=
[];
20 21
private static array
$allowedKeys
=
[
22
self
::
LOGGER
,
23
];
24 25
final public static function set
(string
$key
, Service
$value
)
26
{
27
if
(
!
in_array
(
$key
, self
::
$allowedKeys
)) {
28
throw new
InvalidArgumentException(
'Invalid key given'
);
29
}
30 31
self
::
$services
[
$key
]
=
$value
1   2   3   4   5   6   7   8   9


написать администратору сайта