结构型设计模式的PHP实现

6、适配器模式(Adapter Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php
 
interface MediaPlayer {
    public function play($audioType, $fileName);
}
 
interface AdvancedMediaPlayer {
    public function playVlc($fileName);
    public function playMp4($fileName);
}
 
class VlcPlayer implements AdvancedMediaPlayer {
    public function playVlc($fileName) {
        echo 'Playing vlc file. Name: ' . $fileName . "\n";
    }
 
    public function playMp4($fileName) {}
}
 
class Mp4Player implements AdvancedMediaPlayer {
    public function playVlc($fileName) {}
 
    public function playMp4($fileName) {
        echo 'Playing mp4 file. Name: ' . $fileName . "\n";
    }
}
 
class MediaAdapter implements MediaPlayer {
    private $advancedMusicPlayer;
 
    public function __construct($audioType) {
        if ($audioType === 'vlc') {
            $this->advancedMusicPlayer = new VlcPlayer();
        } else if ($audioType === 'mp4') {
            $this->advancedMusicPlayer = new Mp4Player();
        }
    }
 
 
    public function play($audioType, $fileName) {
        if ($audioType === 'vlc') {
            $this->advancedMusicPlayer->playVlc($fileName);
        } else if ($audioType === 'mp4') {
            $this->advancedMusicPlayer->playMp4($fileName);
        }
    }
}
 
class AudioPlayer implements MediaPlayer {
    private $mediaAdapter;
 
    public function play($audioType, $fileName) {
        if ($audioType === 'mp3') {
            echo 'Playing mp3 file. Name: ' . $fileName . "\n";
        } else if ($audioType === 'vlc' || $audioType === 'mp4') {
            $this->mediaAdapter = new MediaAdapter($audioType);
            $this->mediaAdapter->play($audioType, $fileName);
        } else {
            echo 'Invalid media. ' . $audioType . " format not supported.\n";
        }
    }
}
 
$audioPlayer = new AudioPlayer();
 
$audioPlayer->play('mp3', 'beyond the horizon.mp3');
$audioPlayer->play('mp4', 'alone.mp4');
$audioPlayer->play('vlc', 'far far away.vlc');
$audioPlayer->play('avi', 'mind me.avi');

7、桥接模式(Bridge Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
 
interface DrawAPI {
    public function drawCircle($x, $y, $radius);
}
 
class RedCircle implements DrawAPI {
    public function drawCircle($x, $y, $radius) {
        echo 'Drawing Circle[ color: red, radius: ' . 
          $radius . ', x: ' . $x . ', y: ' .  $y . " ]\n";
    }
}
 
class GreenCircle implements DrawAPI {
    public function drawCircle($x, $y, $radius) {
        echo 'Drawing Circle[ color: green, radius: ' .
          $radius . ', x: ' . $x . ', y: ' .  $y . " ]\n";
    }
}
 
abstract class Shape {
    protected $drawAPI;
 
    public function __construct($drawAPI) {
        $this->drawAPI = $drawAPI;
    }
 
    public abstract function draw();
}
 
class Circle extends Shape {
    private $x, $y, $radius;
 
    public function __construct($x, $y, $radius, $drawAPI) {
        parent::__construct($drawAPI);
        $this->x = $x;
        $this->y = $y;
        $this->radius = $radius;
    }
 
    public function draw() {
        if ($this->drawAPI instanceof DrawAPI) {
            $this->drawAPI->drawCircle($this->x, $this->y, $this->radius);
        }
    }
}
 
$redCircle = new Circle(100, 50, 10, new RedCircle());
$greenCircle = new Circle(50, 100, 20, new GreenCircle());
 
$redCircle->draw();
$greenCircle->draw();

8、过滤器模式(Filter、Criteria Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?php
 
class Person {
    private $name;
    private $gender;
    private $maritalStatus;
 
    public function __construct($name, $gender, $maritalStatus) {
        $this->name = $name;
        $this->gender = $gender;
        $this->maritalStatus = $maritalStatus;
    }
 
    public function getName() {
        return $this->name;
    }
 
    public function getGender() {
        return $this->gender;
    }
 
    public function getMaritalStatus() {
        return $this->maritalStatus;
    }
}
 
interface Criteria {
    public function meetCriteria(array $persons);
}
 
class CriteriaMale implements Criteria {
    public function meetCriteria(array $persons) {
        $malePersons = [];
        foreach ($persons as $person) {
            if ($person instanceof Person && strtoupper($person->getGender()) === 'MALE') {
                $malePersons[] = $person;
            }
        }
        return $malePersons;
    }
}
 
class CriteriaFemale implements Criteria {
    public function meetCriteria(array $persons) {
        $femalePersons = [];
        foreach ($persons as $person) {
            if ($person instanceof Person && strtoupper($person->getGender()) === 'FEMALE') {
                $femalePersons[] = $person;
            }
        }
        return $femalePersons;
    }
}
 
class CriteriaSingle implements Criteria {
    public function meetCriteria(array $persons) {
        $singlePersons = [];
        foreach ($persons as $person) {
            if ($person instanceof Person && strtoupper($person->getMaritalStatus()) === 'SINGLE') {
                $singlePersons[] = $person;
            }
        }
        return $singlePersons;
    }
}
 
class AndCriteria implements Criteria {
    private $criteria;
    private $otherCriteria;
 
    public function __construct(Criteria $criteria, Criteria $otherCriteria) {
        $this->criteria = $criteria;
        $this->otherCriteria = $otherCriteria;
    }
 
    public function meetCriteria(array $persons) {
        $firstCriteriaPersons = $this->criteria->meetCriteria($persons);
        return $this->otherCriteria->meetCriteria($firstCriteriaPersons);
    }
}
 
class OrCriteria implements Criteria {
    private $criteria;
    private $otherCriteria;
 
    public function __construct(Criteria $criteria, Criteria $otherCriteria) {
        $this->criteria = $criteria;
        $this->otherCriteria = $otherCriteria;
    }
 
    public function meetCriteria(array $persons) {
        $firstCriteriaItems = $this->criteria->meetCriteria($persons);
        $otherCriteriaItems = $this->otherCriteria->meetCriteria($persons);
        foreach ($otherCriteriaItems as $otherCriteriaItem) {
            if (!in_array($otherCriteriaItem, $firstCriteriaItems)) { // equate to: !=
                $firstCriteriaItems[] = $otherCriteriaItem;
            }
        }
        return $firstCriteriaItems;
    }
}
 
function printPersons(array $persons) {
    foreach ($persons as $person) {
        echo 'Person : [ Name : ' . $person->getName()
            . ', Gender : ' . $person->getGender()
            . ', Marital Status : ' . $person->getMaritalStatus()
            . " ]\n";
    }
}
 
$persons = [];
$persons[] = new Person('Robert','Male', 'Single');
$persons[] = new Person('John','Male', 'Married');
$persons[] = new Person('Laura','Female', 'Married');
$persons[] = new Person('Diana','Female', 'Single');
$persons[] = new Person('Mike','Male', 'Single');
$persons[] = new Person('Bobby','Male', 'Single');
 
$male = new CriteriaMale();
$female = new CriteriaFemale();
$single = new CriteriaSingle();
$singleMale = new AndCriteria($single, $male);
$singleOrFemale = new OrCriteria($single, $female);
 
echo "Males: \n";
printPersons($male->meetCriteria($persons));
 
echo "\nFemales: \n";
printPersons($female->meetCriteria($persons));
 
echo "\nSingle: \n";
printPersons($single->meetCriteria($persons));
 
echo "\nSingle Males: \n";
printPersons($singleMale->meetCriteria($persons));
 
echo "\nSingle Or Females: \n";
printPersons($singleOrFemale->meetCriteria($persons));

9、组合模式(Composite Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
class Employee {
    private $name;
    private $dept;
    private $salary;
    private $subordinates;
 
    public function __construct(String $name, String $dept, int $salary) {
        $this->name = $name;
        $this->dept = $dept;
        $this->salary = $salary;
        $this->subordinates = [];
    }
 
    public function add(Employee $e) {
        $this->subordinates[] = $e;
    }
 
    public function remove(Employee $e) {
        $subordinates = [];
        foreach ($this->subordinates as $sb) {
            if ($sb !== $e) {
                $subordinates[] = $sb;
            }
        }
        $this->subordinates = $subordinates;
    }
 
    public function getSubordinates(): array {
        return $this->subordinates;
    }
 
    public function toString(): String {
        return 'Employee :[ Name : ' . $this->name . ', dept : ' .  
            $this->dept . ', salary :' . $this->salary . " ]\n";
    }
}
 
function printEmployee(Employee $e) {
    echo $e->toString();
    foreach ($e->getSubordinates() as $subordinate) {
        printEmployee($subordinate);
    }
}
 
$CEO = new Employee('John', 'CEO', 30000);
 
$headSales = new Employee('Robert', 'Head Sales', 20000);
$headMarketing = new Employee('Michel', 'Head Marketing', 20000);
 
$salesExecutive1 = new Employee('Richard', 'Sales', 10000);
$salesExecutive2 = new Employee('Rob', 'Sales', 10000);
 
$clerk1 = new Employee('Laura', 'Marketing', 10000);
$clerk2 = new Employee('Bob', 'Marketing', 10000);
 
$CEO->add($headSales);
$CEO->add($headMarketing);
 
$headSales->add($salesExecutive1);
$headSales->add($salesExecutive2);
 
$headMarketing->add($clerk1);
$headMarketing->add($clerk2);
 
printEmployee($CEO);

10、装饰器模式(Decorator Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
 
interface Shape {
    public function draw();
}
 
class Rectangle implements Shape {
    public function draw() {
        echo 'Shape: Rectangle' . "\n";
    }
}
 
class Circle implements Shape {
    public function draw() {
        echo 'Shape: Circle' . "\n";
    }
}
 
abstract class ShapeDecorator implements Shape {
    protected $decoratedShape;
 
    public function __construct(Shape $decoratedShape) {
        $this->decoratedShape = $decoratedShape;
    }
 
    public function draw(){
        isset($this->decoratedShape) && $this->decoratedShape->draw();
    }
}
 
class RedShapeDecorator extends ShapeDecorator {
    public function __construct(Shape $decoratedShape) {
        parent::__construct($decoratedShape);
    }
 
    public function setRedBorder(Shape $decoratedShape) {
        echo 'Border Color: Red' . "\n";
    }
 
    public function draw() {
        parent::draw();
        $this->setRedBorder($this->decoratedShape);
    }
}
 
// 与抽象工厂模式的demo对比效果更佳
$circle = new Circle();
$redCircle = new RedShapeDecorator(new Circle());
$redRectangle = new RedShapeDecorator(new Rectangle());
echo 'Circle with normal border' . "\n";
$circle->draw();
echo 'Circle of red border' . "\n";
$redCircle->draw();
echo 'Rectangle of red border' . "\n";
$redRectangle->draw();

11、外观模式(Facade Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
 
interface Shape {
    public function draw();
}
 
class Rectangle implements Shape {
    public function draw() {
        echo 'Inside Rectangle::draw() method.' . "\n";
    }
}
 
class Square implements Shape {
    public function draw() {
        echo 'Inside Square::draw() method.' . "\n";
    }
}
 
class Circle implements Shape {
    public function draw() {
        echo 'Inside Circle::draw() method.' . "\n";
    }
}
 
class ShapeMaker {
    private $circle;
    private $rectangle;
    private $square;
 
    public function __construct() {
        $this->circle = new Circle();
        $this->rectangle = new Rectangle();
        $this->square = new Square();
    }
 
    public function drawCircle() {
        $this->circle->draw();
    }
 
    public function drawRectangle() {
        $this->rectangle->draw();
    }
 
    public function drawSquare() {
        $this->square->draw();
    }
}
 
$shapeMaker = new ShapeMaker();
$shapeMaker->drawCircle();
$shapeMaker->drawRectangle();
$shapeMaker->drawSquare();

12、享元模式(Flyweight Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php
 
interface Shape {
    public function draw();
}
 
class Circle implements Shape {
    private $x;
    private $y;
    private $radius;
    private $color;
 
    public function __construct(String $color) {
        $this->color = $color;
    }
 
    public function setX($x) {
        $this->x = $x;
    }
 
    public function setY($y) {
        $this->y = $y;
    }
 
    public function setRadius($radius) {
        $this->radius = $radius;
    }
 
    public function draw() {
        echo 'Circle: Draw() [Color : ' . $this->color . ', x : ' . $this->x
            . ', y : ' . $this->y . ', radius : ' . $this->radius . "]\n";
    }
}
 
class ShapeFactory {
    private static $circleMap = [];
 
    public static function getCircle(String $color): Circle {
        if (!isset(self::$circleMap[$color])) {
            self::$circleMap[$color] = new Circle($color);
            echo 'Creating circle of color : ' . $color . "\n";
        }
        return self::$circleMap[$color];
    }
}
 
function getRandomNum() {
    return rand(0, 100);
}
 
function getRandomColor() {
    $colors = ['Red', 'Green', 'Blue', 'White', 'Black'];
    return $colors[rand(0, count($colors) - 1)];
}
 
for ($i = 0; $i < 20; ++$i) {
    $circle = ShapeFactory::getCircle(getRandomColor());
    $circle->setX(getRandomNum());
    $circle->setY(getRandomNum());
    $circle->setRadius(100);
    $circle->draw();
}

13、代理模式(Proxy Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
 
interface Image {
    public function display();
}
 
class RealImage implements Image {
    private $fileName;
 
    public function __construct(String $fileName) {
        $this->fileName = $fileName;
        $this->loadFromDisk($fileName);
    }
 
    public function display() {
        echo 'Displaying ' . $this->fileName . "\n";
    }
 
    public function loadFromDisk(String $fileName) {
        echo 'Loading ' . $fileName . "\n";
    }
}
 
class ProxyImage implements Image {
    private $fileName;
    private $realImage;
 
    public function __construct(String $fileName) {
        $this->fileName = $fileName;
    }
 
    public function display() {
        if (!$this->realImage) {
            $this->realImage = new RealImage($this->fileName);
        }
        $this->realImage->display();
    }
}
 
$image = new ProxyImage("test_10mb.jpg");
// 图像将从磁盘加载
$image->display();
// 图像将无法从磁盘加载
$image->display();

发表评论

电子邮件地址不会被公开。 必填项已用*标注