├── AbstractFactoryWithReflection
├── config.php
├── User.php
├── Article.php
├── MySQLUser.php
├── SQLiteUser.php
├── MySQLArticle.php
├── SQLiteArticle.php
├── index.php
└── Factory.php
├── AbstractFactoryWithSimpleFactory
├── config.php
├── User.php
├── Article.php
├── MySQLUser.php
├── SQLiteUser.php
├── MySQLArticle.php
├── SQLiteArticle.php
├── index.php
└── Factory.php
├── vendor
├── autoload.php
└── composer
│ ├── autoload_classmap.php
│ ├── autoload_namespaces.php
│ ├── autoload_psr4.php
│ ├── autoload_static.php
│ ├── LICENSE
│ ├── autoload_real.php
│ └── ClassLoader.php
├── Proxy
├── Subject.php
├── RealSubject.php
├── index.php
└── Proxy.php
├── Observer
├── Observer.php
├── Subject.php
├── SMSObserver.php
├── EmailObserver.php
├── index.php
└── SubjectAbstract.php
├── Bridge
├── Color.php
├── Red.php
├── Green.php
├── Yellow.php
├── Circle.php
├── Square.php
├── Triangle.php
├── Graph.php
└── index.php
├── Command
├── CommandInterface.php
├── Receiver.php
├── Invoker.php
├── index.php
└── Command.php
├── Facade
├── Encrypt.php
├── File.php
├── index.php
└── Facade.php
├── FactoryMethod
├── Factory.php
├── Add.php
├── AddFactory.php
├── DivFactory.php
├── MulFactory.php
├── SubFactory.php
├── Mul.php
├── Sub.php
├── Div.php
├── Operation.php
└── index.php
├── Template
├── Huawei.php
├── Xiaomi.php
├── index.php
└── Phone.php
├── SafeComposite
├── File.php
├── Component.php
├── Dir.php
└── index.php
├── SimpleFactory
├── Add.php
├── Mul.php
├── Sub.php
├── Div.php
├── Factory.php
├── Operation.php
├── Bad.php
└── index.php
├── Decorator
├── Food.php
├── Decorator.php
├── Kaolengmian.php
├── Shouzhuabing.php
├── Egg.php
├── Latiao.php
├── Sausage.php
└── index.php
├── Flyweight
├── ConcreteFlyweight.php
├── UnsharedConcreteFlyweight.php
├── Flyweight.php
├── FlyweightFactory.php
└── index.php
├── Prototype
├── Car.php
├── ShallowDrive.php
├── DeepDrive.php
└── index.php
├── composer.json
├── Iterator
├── IteratorInterface.php
├── ContainerInterface.php
├── index.php
├── NameContainer.php
└── NameIterator.php
├── ClassAdapter
├── Target.php
├── Adaptee.php
├── Adapter.php
└── index.php
├── AbstractFactory
├── User.php
├── Article.php
├── Factory.php
├── MySQLUser.php
├── SQLiteUser.php
├── MySQLArticle.php
├── SQLiteArticle.php
├── MySQLFactory.php
├── SQLiteFactory.php
└── index.php
├── ObjectAdapter
├── Adaptee.php
├── Target.php
├── index.php
└── Adapter.php
├── TransparentComposite
├── File.php
├── Component.php
├── Dir.php
└── index.php
├── singleton
└── index.php
├── readme.md
└── index.html
/AbstractFactoryWithReflection/config.php:
--------------------------------------------------------------------------------
1 | 'SQLite'
5 | ];
--------------------------------------------------------------------------------
/AbstractFactoryWithSimpleFactory/config.php:
--------------------------------------------------------------------------------
1 | 'SQLite'
5 | ];
--------------------------------------------------------------------------------
/vendor/autoload.php:
--------------------------------------------------------------------------------
1 | array($baseDir . '/'),
10 | );
11 |
--------------------------------------------------------------------------------
/Observer/Observer.php:
--------------------------------------------------------------------------------
1 | ';
15 | $this->notify();
16 | }
17 | }
--------------------------------------------------------------------------------
/Bridge/Red.php:
--------------------------------------------------------------------------------
1 | ';
18 | }
19 | }
--------------------------------------------------------------------------------
/Bridge/Yellow.php:
--------------------------------------------------------------------------------
1 | ';
18 | }
19 | }
--------------------------------------------------------------------------------
/FactoryMethod/Factory.php:
--------------------------------------------------------------------------------
1 | color->run()} 的圆形";
19 | }
20 | }
--------------------------------------------------------------------------------
/Bridge/Square.php:
--------------------------------------------------------------------------------
1 | color->run()} 的正方形";
19 | }
20 | }
--------------------------------------------------------------------------------
/Bridge/Triangle.php:
--------------------------------------------------------------------------------
1 | color->run()} 的三角形";
19 | }
20 | }
--------------------------------------------------------------------------------
/Template/Huawei.php:
--------------------------------------------------------------------------------
1 | ';
20 | }
21 | }
--------------------------------------------------------------------------------
/Template/Xiaomi.php:
--------------------------------------------------------------------------------
1 | ';
20 | }
21 | }
--------------------------------------------------------------------------------
/SafeComposite/File.php:
--------------------------------------------------------------------------------
1 | name .'
';
19 | }
20 | }
--------------------------------------------------------------------------------
/FactoryMethod/Add.php:
--------------------------------------------------------------------------------
1 | numberA + $this->numberB;
21 | }
22 | }
--------------------------------------------------------------------------------
/FactoryMethod/AddFactory.php:
--------------------------------------------------------------------------------
1 | numberA + $this->numberB;
21 | }
22 | }
--------------------------------------------------------------------------------
/FactoryMethod/Mul.php:
--------------------------------------------------------------------------------
1 | numberA * $this->numberB;
21 | }
22 | }
--------------------------------------------------------------------------------
/FactoryMethod/Sub.php:
--------------------------------------------------------------------------------
1 | numberA - $this->numberB;
21 | }
22 | }
--------------------------------------------------------------------------------
/SimpleFactory/Mul.php:
--------------------------------------------------------------------------------
1 | numberA * $this->numberB;
21 | }
22 | }
--------------------------------------------------------------------------------
/SimpleFactory/Sub.php:
--------------------------------------------------------------------------------
1 | numberA - $this->numberB;
21 | }
22 | }
--------------------------------------------------------------------------------
/Decorator/Food.php:
--------------------------------------------------------------------------------
1 | name . $content . '
';
20 | }
21 | }
--------------------------------------------------------------------------------
/Prototype/Car.php:
--------------------------------------------------------------------------------
1 | name = $name;
26 | }
27 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "baijunyao/design-patterns",
3 | "description": "design patterns",
4 | "type": "project",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "baijunyao",
9 | "email": "baijunyao@baijunyao.com"
10 | }
11 | ],
12 | "require": {},
13 | "autoload": {
14 | "psr-4": {
15 | "Baijunyao\\DesignPatterns\\": ""
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Iterator/IteratorInterface.php:
--------------------------------------------------------------------------------
1 | money;
26 | }
27 | }
--------------------------------------------------------------------------------
/ObjectAdapter/Adaptee.php:
--------------------------------------------------------------------------------
1 | money;
26 | }
27 | }
--------------------------------------------------------------------------------
/ObjectAdapter/Target.php:
--------------------------------------------------------------------------------
1 | action();
22 | }
23 | }
24 |
25 | $client = new Client();
26 | $client->run();
--------------------------------------------------------------------------------
/Facade/index.php:
--------------------------------------------------------------------------------
1 | encryptContent();
22 | }
23 | }
24 |
25 | $client = new Client();
26 | $client->run();
--------------------------------------------------------------------------------
/AbstractFactory/Article.php:
--------------------------------------------------------------------------------
1 | food = $food;
25 | }
26 | }
--------------------------------------------------------------------------------
/AbstractFactoryWithSimpleFactory/Article.php:
--------------------------------------------------------------------------------
1 | money = '$5';
19 | }
20 |
21 | /**
22 | * 通知
23 | */
24 | public function notify()
25 | {
26 | echo '通知';
27 | }
28 | }
--------------------------------------------------------------------------------
/FactoryMethod/Div.php:
--------------------------------------------------------------------------------
1 | numberB == 0) {
21 | throw new \InvalidArgumentException('除数不能为0');
22 | }
23 | return $this->numberA / $this->numberB;
24 | }
25 | }
--------------------------------------------------------------------------------
/SimpleFactory/Div.php:
--------------------------------------------------------------------------------
1 | numberB == 0) {
21 | throw new \InvalidArgumentException('除数不能为0');
22 | }
23 | return $this->numberA / $this->numberB;
24 | }
25 | }
--------------------------------------------------------------------------------
/AbstractFactory/MySQLUser.php:
--------------------------------------------------------------------------------
1 | action();
22 |
23 | echo '
';
24 |
25 | $huawei = new Huawei();
26 | $huawei->action();
27 | }
28 | }
29 |
30 | $client = new Client();
31 | $client->run();
--------------------------------------------------------------------------------
/AbstractFactoryWithReflection/MySQLUser.php:
--------------------------------------------------------------------------------
1 | food->name() . '+蛋';
21 | }
22 |
23 | /**
24 | * 价格
25 | *
26 | * @return int|mixed
27 | */
28 | public function price()
29 | {
30 | return $this->food->price() + 1;
31 | }
32 | }
--------------------------------------------------------------------------------
/AbstractFactoryWithSimpleFactory/MySQLUser.php:
--------------------------------------------------------------------------------
1 | food->name() . '+辣条';
21 | }
22 |
23 | /**
24 | * 价格
25 | *
26 | * @return int|mixed
27 | */
28 | public function price()
29 | {
30 | return $this->food->price() + 3;
31 | }
32 | }
--------------------------------------------------------------------------------
/AbstractFactoryWithReflection/MySQLArticle.php:
--------------------------------------------------------------------------------
1 | food->name() . '+肠';
21 | }
22 |
23 | /**
24 | * 价格
25 | *
26 | * @return int|mixed
27 | */
28 | public function price()
29 | {
30 | return $this->food->price() + 2;
31 | }
32 | }
--------------------------------------------------------------------------------
/Bridge/Graph.php:
--------------------------------------------------------------------------------
1 | color = $color;
27 | }
28 |
29 | /**
30 | * @return mixed
31 | */
32 | abstract public function draw();
33 | }
--------------------------------------------------------------------------------
/AbstractFactoryWithSimpleFactory/MySQLArticle.php:
--------------------------------------------------------------------------------
1 | command = $command;
23 | }
24 |
25 | /**
26 | * 执行
27 | */
28 | public function run()
29 | {
30 | $this->command->execute();
31 | }
32 | }
--------------------------------------------------------------------------------
/Flyweight/UnsharedConcreteFlyweight.php:
--------------------------------------------------------------------------------
1 | name . $content . '
';
20 | }
21 |
22 | /**
23 | * 附加的删除方法
24 | */
25 | public function delete()
26 | {
27 | $this->name = '';
28 | }
29 | }
--------------------------------------------------------------------------------
/SafeComposite/Component.php:
--------------------------------------------------------------------------------
1 | name = $name;
25 | }
26 |
27 | /**
28 | * @return mixed
29 | */
30 | abstract public function display();
31 | }
--------------------------------------------------------------------------------
/Flyweight/Flyweight.php:
--------------------------------------------------------------------------------
1 | name = $name;
27 | }
28 |
29 | /**
30 | * @param $content
31 | */
32 | public function show($content){}
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/TransparentComposite/File.php:
--------------------------------------------------------------------------------
1 | name .'
';
28 | }
29 | }
--------------------------------------------------------------------------------
/AbstractFactory/SQLiteArticle.php:
--------------------------------------------------------------------------------
1 | setCommand($command);
27 | $invoker->run();
28 | }
29 | }
30 |
31 | $client = new Client();
32 | $client->run();
--------------------------------------------------------------------------------
/Flyweight/FlyweightFactory.php:
--------------------------------------------------------------------------------
1 | flyweights[$name])){
27 | $this->flyweights[$name]=new ConcreteFlyweight($name);
28 | }
29 | return $this->flyweights[$name];
30 | }
31 | }
--------------------------------------------------------------------------------
/Observer/index.php:
--------------------------------------------------------------------------------
1 | attach($emailObserver);
25 | $subject->attach($SMSObserver);
26 | $subject->publish();
27 | }
28 | }
29 |
30 | $client = new Client();
31 | $client->run();
--------------------------------------------------------------------------------
/AbstractFactory/MySQLFactory.php:
--------------------------------------------------------------------------------
1 | car = $car;
30 | }
31 |
32 | public function show()
33 | {
34 | echo '开始驾驶'.$this->car->name;
35 | echo '
';
36 | }
37 | }
--------------------------------------------------------------------------------
/ClassAdapter/index.php:
--------------------------------------------------------------------------------
1 | pay();
23 | echo '
';
24 |
25 | // 适配器
26 | $adapter = new Adapter();
27 | $adapter->pay();
28 | echo '
';
29 |
30 | $adapter->notify();
31 | }
32 | }
33 |
34 | $client = new Client();
35 | $client->run();
--------------------------------------------------------------------------------
/Proxy/Proxy.php:
--------------------------------------------------------------------------------
1 | realSubject = new RealSubject();
27 | }
28 |
29 | /*
30 | * 执行操作
31 | */
32 | public function action()
33 | {
34 | $this->realSubject->action();
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/AbstractFactoryWithReflection/SQLiteArticle.php:
--------------------------------------------------------------------------------
1 | pay();
23 | echo '
';
24 |
25 | // 适配器
26 | $adapter = new Adapter($adaptee);
27 | $adapter->pay();
28 | echo '
';
29 |
30 | $adapter->notify();
31 | }
32 | }
33 |
34 | $client = new Client();
35 | $client->run();
--------------------------------------------------------------------------------
/AbstractFactoryWithSimpleFactory/SQLiteArticle.php:
--------------------------------------------------------------------------------
1 | observers[] = $observer;
23 | }
24 |
25 | /**
26 | * 通知
27 | */
28 | public function notify()
29 | {
30 | foreach ($this->observers as $k => $v) {
31 | $v->update();
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Command/Command.php:
--------------------------------------------------------------------------------
1 | receiver = $receiver;
25 | }
26 |
27 | /**
28 | * @return mixed|void
29 | */
30 | public function execute()
31 | {
32 | $this->receiver->action();
33 | }
34 | }
--------------------------------------------------------------------------------
/Iterator/index.php:
--------------------------------------------------------------------------------
1 | add('张三');
22 | $nameContainer->add('李四');
23 | $nameContainer->add('王麻子');
24 |
25 | $nameIterator = $nameContainer->getIterator();
26 |
27 | while ($nameIterator->hasNext()) {
28 | echo $nameIterator->next();
29 | }
30 | }
31 | }
32 |
33 | $client = new Client();
34 | $client->run();
--------------------------------------------------------------------------------
/Prototype/DeepDrive.php:
--------------------------------------------------------------------------------
1 | car = $car;
30 | }
31 |
32 | public function show()
33 | {
34 | echo '开始驾驶'.$this->car->name;
35 | echo '
';
36 | }
37 |
38 | public function __clone()
39 | {
40 | $this->car = clone $this->car;
41 | }
42 | }
--------------------------------------------------------------------------------
/Iterator/NameContainer.php:
--------------------------------------------------------------------------------
1 | nameArray[] = $name;
27 | }
28 |
29 | /**
30 | * 获取迭代器
31 | *
32 | * @return \Baijunyao\DesignPatterns\Iterator\NameIterator|mixed
33 | */
34 | public function getIterator()
35 | {
36 | return new NameIterator($this->nameArray);
37 | }
38 | }
--------------------------------------------------------------------------------
/TransparentComposite/Component.php:
--------------------------------------------------------------------------------
1 | name = $name;
25 | }
26 |
27 | /**
28 | * 添加子节点
29 | *
30 | * @return mixed
31 | */
32 | abstract public function add();
33 |
34 | /**
35 | * 展示名称
36 | *
37 | * @return mixed
38 | */
39 | abstract public function display();
40 | }
--------------------------------------------------------------------------------
/Template/Phone.php:
--------------------------------------------------------------------------------
1 | powerOn();
18 | $this->showLogo();
19 | $this->callUp();
20 | }
21 |
22 | /**
23 | * 开机
24 | */
25 | protected function powerOn()
26 | {
27 | echo '开机' . '
';
28 | }
29 |
30 | /**
31 | * logo
32 | *
33 | * @return mixed
34 | */
35 | abstract protected function showLogo();
36 |
37 | /**
38 | * 打电话
39 | */
40 | protected function callUp()
41 | {
42 | echo '打电话' . '
';
43 | }
44 | }
--------------------------------------------------------------------------------
/Facade/Facade.php:
--------------------------------------------------------------------------------
1 | file = new File();
28 | $this->encrypt = new Encrypt();
29 | }
30 |
31 | /**
32 | * 获取文件内容并加密
33 | */
34 | public function encryptContent()
35 | {
36 | echo $this->file->content();
37 | echo '
';
38 | echo $this->encrypt->encrypt();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ObjectAdapter/Adapter.php:
--------------------------------------------------------------------------------
1 | adaptee = $adaptee;
22 | $adaptee->money = '$5';
23 | }
24 |
25 | /**
26 | * 支付
27 | *
28 | * @return mixed|void
29 | */
30 | public function pay()
31 | {
32 | $this->adaptee->pay();
33 | }
34 |
35 | /**
36 | * 通知
37 | *
38 | * @return mixed|void
39 | */
40 | public function notify()
41 | {
42 | echo '通知';
43 | }
44 | }
--------------------------------------------------------------------------------
/SafeComposite/Dir.php:
--------------------------------------------------------------------------------
1 | children[] = $component;
26 | }
27 |
28 | /**
29 | * @return mixed|string
30 | */
31 | public function display()
32 | {
33 | $nameStr = $this->name .'
';
34 | foreach ($this->children as $k => $v) {
35 |
36 | $nameStr .= '--' . $v->display();
37 | }
38 | return $nameStr;
39 | }
40 | }
--------------------------------------------------------------------------------
/AbstractFactoryWithReflection/index.php:
--------------------------------------------------------------------------------
1 | createUser();
24 | $user->insert();
25 | echo '
';
26 | $user->select();
27 |
28 | echo '
';
29 |
30 | // 创建 article
31 | $article = $factory->createArticle();
32 | $article->insert();
33 | echo '
';
34 | $article->select();
35 | }
36 | }
37 |
38 | $client = new Client();
39 | $client->run();
--------------------------------------------------------------------------------
/TransparentComposite/Dir.php:
--------------------------------------------------------------------------------
1 | children[] = $component;
26 | }
27 |
28 | /**
29 | * @return mixed|string
30 | */
31 | public function display()
32 | {
33 | $nameStr = $this->name .'
';
34 | foreach ($this->children as $k => $v) {
35 |
36 | $nameStr .= '--' . $v->display();
37 | }
38 | return $nameStr;
39 | }
40 | }
--------------------------------------------------------------------------------
/AbstractFactoryWithSimpleFactory/index.php:
--------------------------------------------------------------------------------
1 | createUser();
24 | $user->insert();
25 | echo '
';
26 | $user->select();
27 |
28 | echo '
';
29 |
30 | // 创建 article
31 | $article = $factory->createArticle();
32 | $article->insert();
33 | echo '
';
34 | $article->select();
35 | }
36 | }
37 |
38 | $client = new Client();
39 | $client->run();
--------------------------------------------------------------------------------
/SimpleFactory/Factory.php:
--------------------------------------------------------------------------------
1 | numberA = $number;
42 | }
43 |
44 | /**
45 | * 给 numberB 赋值
46 | *
47 | * @param $number
48 | */
49 | public function setNumberB($number)
50 | {
51 | $this->numberB = $number;
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/SimpleFactory/Operation.php:
--------------------------------------------------------------------------------
1 | numberA = $number;
42 | }
43 |
44 | /**
45 | * 给 numberB 赋值
46 | *
47 | * @param $number
48 | */
49 | public function setNumberB($number)
50 | {
51 | $this->numberB = $number;
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/vendor/composer/autoload_static.php:
--------------------------------------------------------------------------------
1 |
11 | array (
12 | 'Baijunyao\\DesignPatterns\\' => 25,
13 | ),
14 | );
15 |
16 | public static $prefixDirsPsr4 = array (
17 | 'Baijunyao\\DesignPatterns\\' =>
18 | array (
19 | 0 => __DIR__ . '/../..' . '/',
20 | ),
21 | );
22 |
23 | public static function getInitializer(ClassLoader $loader)
24 | {
25 | return \Closure::bind(function () use ($loader) {
26 | $loader->prefixLengthsPsr4 = ComposerStaticInit88798c90f3cb8871fa59cc0f15b5142f::$prefixLengthsPsr4;
27 | $loader->prefixDirsPsr4 = ComposerStaticInit88798c90f3cb8871fa59cc0f15b5142f::$prefixDirsPsr4;
28 |
29 | }, null, ClassLoader::class);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Flyweight/index.php:
--------------------------------------------------------------------------------
1 | getFlyweight('170cm的模特');
22 | $zhangsan1->show('第1件L号的衣服');
23 |
24 | $zhangsan2 = $flyweight->getFlyweight('170cm的模特');
25 | $zhangsan2->show('第99件L号的衣服');
26 |
27 | var_dump($zhangsan1 === $zhangsan2);
28 | echo '
';
29 |
30 | $lisi = $flyweight->getFlyweight('180cm的模特');
31 | $lisi->show('第1件XXL号的衣服');
32 |
33 | $wangmazi = new UnsharedConcreteFlyweight('190cm的模特');
34 | $wangmazi->show('第1件XXXL号的衣服');
35 | $wangmazi->delete();
36 | $wangmazi->show('第1件XXXL号的衣服');
37 | }
38 | }
39 |
40 | $client = new Client();
41 | $client->run();
--------------------------------------------------------------------------------
/Iterator/NameIterator.php:
--------------------------------------------------------------------------------
1 | nameArray = $nameArray;
30 | }
31 |
32 | /**
33 | * 判断是否还有下一个姓名
34 | *
35 | * @return bool|mixed
36 | */
37 | public function hasNext()
38 | {
39 | return $this->index < count($this->nameArray);
40 | }
41 |
42 | /**
43 | * 下一个姓名
44 | *
45 | * @return mixed|void
46 | */
47 | public function next()
48 | {
49 | if ($this->hasNext()) {
50 | echo $this->nameArray[$this->index] . '
';
51 | $this->index++;
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/vendor/composer/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) Nils Adermann, Jordi Boggiano
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is furnished
9 | to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 |
22 |
--------------------------------------------------------------------------------
/SimpleFactory/Bad.php:
--------------------------------------------------------------------------------
1 | add($classAdapter);
27 | $designPatterns->add($objectAdapter);
28 | $designPatterns->add($safeComposite);
29 |
30 | $componentFile = new File('Component.php');
31 | $dirFile = new File('Dir.php');
32 | $fileFile = new File('File.php');
33 | $indexFile = new File('index.php');
34 |
35 | $safeComposite->add($componentFile);
36 | $safeComposite->add($dirFile);
37 | $safeComposite->add($fileFile);
38 | $safeComposite->add($indexFile);
39 |
40 | echo $designPatterns->display();
41 | }
42 | }
43 |
44 | $client = new Client();
45 | $client->run();
46 |
--------------------------------------------------------------------------------
/FactoryMethod/index.php:
--------------------------------------------------------------------------------
1 | setNumberA(1);
23 | $operation->setNumberB(2);
24 | $result = $operation->getResult();
25 | echo $result;
26 |
27 | echo '
';
28 |
29 | // 计算 3+4
30 | $operation = new Add();
31 | $operation->setNumberA(3);
32 | $operation->setNumberB(4);
33 | $result = $operation->getResult();
34 | echo $result;
35 | }
36 |
37 | /**
38 | * 好的示例 new 产品对应的工厂
39 | */
40 | public function good()
41 | {
42 | $factory = new AddFactory();
43 | $operation = $factory->create();
44 | $operation->setNumberA(1);
45 | $operation->setNumberB(2);
46 | $result = $operation->getResult();
47 | echo $result;
48 | }
49 | }
50 |
51 |
52 | $client = new Client();
53 | $client->bad();
54 | echo '
';
55 | $client->good();
--------------------------------------------------------------------------------
/Decorator/index.php:
--------------------------------------------------------------------------------
1 | name();
23 | echo $shouzhuabing->price() . '元';
24 | echo '
';
25 |
26 | // 烤冷面
27 | $kaolengmian = new Kaolengmian();
28 | echo $kaolengmian->name();
29 | echo $kaolengmian->price() . '元';
30 | echo '
';
31 |
32 | // 手抓饼+蛋
33 | $egg = new Egg($shouzhuabing);
34 | echo $egg->name();
35 | echo $egg->price() . '元';
36 | echo '
';
37 |
38 | // 手抓饼+肠
39 | $sausage = new Sausage($kaolengmian);
40 | echo $sausage->name();
41 | echo $sausage->price() . '元';
42 | echo '
';
43 |
44 | // 烤冷面+辣条
45 | $latiao = new Latiao($shouzhuabing);
46 | echo $latiao->name();
47 | echo $latiao->price() . '元';
48 | echo '
';
49 | }
50 | }
51 |
52 | $client = new Client();
53 | $client->run();
54 |
--------------------------------------------------------------------------------
/TransparentComposite/index.php:
--------------------------------------------------------------------------------
1 | add($classAdapter);
27 | $designPatterns->add($objectAdapter);
28 | $designPatterns->add($transparentComposite);
29 |
30 | $componentFile = new File('Component.php');
31 | $dirFile = new File('Dir.php');
32 | $fileFile = new File('File.php');
33 | $indexFile = new File('index.php');
34 |
35 | $transparentComposite->add($componentFile);
36 | $transparentComposite->add($dirFile);
37 | $transparentComposite->add($fileFile);
38 | $transparentComposite->add($indexFile);
39 |
40 | echo $designPatterns->display();
41 | }
42 | }
43 |
44 | $client = new Client();
45 | $client->run();
46 |
--------------------------------------------------------------------------------
/AbstractFactory/index.php:
--------------------------------------------------------------------------------
1 | createUser();
24 | $user->insert();
25 | echo '
';
26 | $user->select();
27 |
28 | echo '
';
29 |
30 | $factory = new MySQLFactory();
31 | // 创建 article
32 | $article = $factory->createArticle();
33 | $article->insert();
34 | echo '
';
35 | $article->select();
36 |
37 | echo '
';
38 |
39 | // 使用 SQLite
40 | $factory = new SQLiteFactory();
41 | // 创建 user
42 | $user = $factory->createUser();
43 | $user->insert();
44 | echo '
';
45 | $user->select();
46 |
47 | echo '
';
48 |
49 | $factory = new SQLiteFactory();
50 | // 创建 article
51 | $article = $factory->createArticle();
52 | $article->insert();
53 | echo '
';
54 | $article->select();
55 | }
56 | }
57 |
58 | $client = new Client();
59 | $client->run();
--------------------------------------------------------------------------------
/Prototype/index.php:
--------------------------------------------------------------------------------
1 | name = '特斯拉';
22 |
23 | $shallowDrive = new ShallowDrive();
24 | $shallowDrive->setCar($car);
25 | $shallowDrive->show();
26 |
27 | $cloneDrive = clone $shallowDrive;
28 | $cloneDrive->show();
29 |
30 | echo '
';
31 |
32 | $car->name = '凯迪拉克';
33 | $shallowDrive->show();
34 | $cloneDrive->show();
35 | }
36 |
37 | /**
38 | *
39 | */
40 | public function deepCopy()
41 | {
42 | $car = new Car();
43 | $car->name = '特斯拉';
44 |
45 | $deepDrive = new DeepDrive();
46 | $deepDrive->setCar($car);
47 | $deepDrive->show();
48 |
49 | $cloneDrive = clone $deepDrive;
50 | $cloneDrive->show();
51 |
52 | echo '
';
53 |
54 | $car->name = '凯迪拉克';
55 | $deepDrive->show();
56 | $cloneDrive->show();
57 | }
58 | }
59 |
60 | $client = new Client();
61 | $client->shallowCopy();
62 | echo '
-----------------------------
';
63 | $client->deepCopy();
--------------------------------------------------------------------------------
/SimpleFactory/index.php:
--------------------------------------------------------------------------------
1 | getResult(1, '+', 2);
22 | echo $result;
23 | }
24 |
25 | /**
26 | * 不好的示例2
27 | *
28 | * @return int
29 | */
30 | public function bad2()
31 | {
32 | // 计算 1+2
33 | $operation = new Add();
34 | $operation->setNumberA(1);
35 | $operation->setNumberB(2);
36 | $result = $operation->getResult();
37 | echo $result;
38 |
39 | echo '
';
40 |
41 | // 计算 3+4
42 | $operation = new Add();
43 | $operation->setNumberA(3);
44 | $operation->setNumberB(4);
45 | $result = $operation->getResult();
46 | echo $result;
47 | }
48 |
49 | /**
50 | * 好的示例
51 | */
52 | public function good()
53 | {
54 | $factory = new Factory();
55 | $operation = $factory->create('+');
56 | $operation->setNumberA(1);
57 | $operation->setNumberB(2);
58 | $result = $operation->getResult();
59 | echo $result;
60 | }
61 | }
62 |
63 |
64 | $client = new Client();
65 | $client->bad();
66 | echo '
';
67 | $client->bad2();
68 | echo '
';
69 | $client->good();
--------------------------------------------------------------------------------
/AbstractFactoryWithSimpleFactory/Factory.php:
--------------------------------------------------------------------------------
1 | db = $config['driver'];
19 | }
20 |
21 | /**
22 | * 创建 User 产品
23 | *
24 | * @return MySQLUser|SQLiteUser
25 | */
26 | public function createUser()
27 | {
28 | switch ($this->db) {
29 | case 'MySQL':
30 | $user = new MySQLUser();
31 | break;
32 | case 'SQLite':
33 | $user = new SQLiteUser();
34 | break;
35 | default:
36 | throw new \InvalidArgumentException('暂不支持的数据库类型');
37 | }
38 | return $user;
39 | }
40 |
41 | /**
42 | * 创建 Article 产品
43 | *
44 | * @return MySQLArticle|SQLiteArticle
45 | */
46 | public function createArticle()
47 | {
48 | switch ($this->db) {
49 | case 'MySQL':
50 | $article = new MySQLArticle();
51 | break;
52 | case 'SQLite':
53 | $article = new SQLiteArticle();
54 | break;
55 | default:
56 | throw new \InvalidArgumentException('暂不支持的数据库类型');
57 | }
58 | return $article;
59 | }
60 | }
--------------------------------------------------------------------------------
/Bridge/index.php:
--------------------------------------------------------------------------------
1 | draw();
27 | echo '
';
28 |
29 | // 黄色的正方形
30 | $yellowSquare = new Square($yellow);
31 | $yellowSquare->draw();
32 | echo '
';
33 |
34 | // 绿色的正方形
35 | $greenSquare = new Square($green);
36 | $greenSquare->draw();
37 | echo '
';
38 |
39 |
40 | // 红色的三角形
41 | $redTriangle = new Triangle($red);
42 | $redTriangle->draw();
43 | echo '
';
44 |
45 | // 黄色的三角形
46 | $yellowTriangle = new Triangle($yellow);
47 | $yellowTriangle->draw();
48 | echo '
';
49 |
50 | // 绿色的三角形
51 | $greenTriangle = new Triangle($green);
52 | $greenTriangle->draw();
53 | echo '
';
54 |
55 |
56 | // 红色的圆形
57 | $redCircle = new Circle($red);
58 | $redCircle->draw();
59 | echo '
';
60 |
61 | // 黄色的圆形
62 | $yellowCircle = new Circle($yellow);
63 | $yellowCircle->draw();
64 | echo '
';
65 |
66 | // 绿色的圆形
67 | $greenCircle = new Circle($green);
68 | $greenCircle->draw();
69 | echo '
';
70 |
71 | }
72 | }
73 |
74 | $client = new Client();
75 | $client->run();
--------------------------------------------------------------------------------
/AbstractFactoryWithReflection/Factory.php:
--------------------------------------------------------------------------------
1 | db = $config['driver'];
34 | }
35 |
36 | /**
37 | * 创建 User 产品
38 | *
39 | * @return MySQLUser|SQLiteUser
40 | */
41 | public function createUser()
42 | {
43 | $className = $this->namespace . $this->db . 'User';
44 | try {
45 | $class = new ReflectionClass($className);
46 | $user = $class->newInstance();
47 | } catch (ReflectionException $Exception) {
48 | throw new \InvalidArgumentException('暂不支持的数据库类型');
49 | }
50 | return $user;
51 | }
52 |
53 | /**
54 | * 创建 Article 产品
55 | *
56 | * @return MySQLArticle|SQLiteArticle
57 | */
58 | public function createArticle()
59 | {
60 | $className = $this->namespace . $this->db . 'Article';
61 | try {
62 | $class = new ReflectionClass($className);
63 | $article = $class->newInstance();
64 | } catch (ReflectionException $Exception) {
65 | throw new \InvalidArgumentException('暂不支持的数据库类型');
66 | }
67 | return $article;
68 | }
69 | }
--------------------------------------------------------------------------------
/vendor/composer/autoload_real.php:
--------------------------------------------------------------------------------
1 | = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27 | if ($useStaticLoader) {
28 | require_once __DIR__ . '/autoload_static.php';
29 |
30 | call_user_func(\Composer\Autoload\ComposerStaticInit88798c90f3cb8871fa59cc0f15b5142f::getInitializer($loader));
31 | } else {
32 | $map = require __DIR__ . '/autoload_namespaces.php';
33 | foreach ($map as $namespace => $path) {
34 | $loader->set($namespace, $path);
35 | }
36 |
37 | $map = require __DIR__ . '/autoload_psr4.php';
38 | foreach ($map as $namespace => $path) {
39 | $loader->setPsr4($namespace, $path);
40 | }
41 |
42 | $classMap = require __DIR__ . '/autoload_classmap.php';
43 | if ($classMap) {
44 | $loader->addClassMap($classMap);
45 | }
46 | }
47 |
48 | $loader->register(true);
49 |
50 | return $loader;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/singleton/index.php:
--------------------------------------------------------------------------------
1 | ';
45 | var_dump($db2);
46 | echo '
';
47 | var_dump($db3);
48 | echo '
';
49 | var_dump($db4);
50 | echo '
';
51 | var_dump($db5);
52 | echo '
';
53 |
54 |
55 | /**
56 | * 单例
57 | *
58 | * Class Db2
59 | * @package Baijunyao\DesignPatterns\Singleton
60 | */
61 | class Db2
62 | {
63 | private static $instance = null;
64 |
65 | public static function getInstance()
66 | {
67 | if (null === static::$instance) {
68 | static::$instance = new static();
69 | }
70 |
71 | return static::$instance;
72 | }
73 |
74 | /**
75 | * 防止使用 new 创建多个实例
76 | *
77 | * Db2 constructor.
78 | */
79 | private function __construct()
80 | {
81 | }
82 |
83 | /**
84 | * 防止 clone 多个实例
85 | */
86 | private function __clone()
87 | {
88 | }
89 |
90 | /**
91 | * 防止反序列化
92 | */
93 | private function __wakeup()
94 | {
95 | }
96 | }
97 |
98 | $db6 = Db2::getInstance();
99 | $db7 = Db2::getInstance();
100 |
101 | var_dump($db6);
102 | echo '
';
103 | var_dump($db7);
104 | echo '
';
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | ### 文章
2 | 1. [php设计模式(一)序言](https://baijunyao.com/article/158)
3 | 2. [php设计模式(二)单例模式](https://baijunyao.com/article/159)
4 | 3. [php设计模式(三)简单工厂模式](https://baijunyao.com/article/161)
5 | 4. [php设计模式(四)工厂方法模式](https://baijunyao.com/article/162)
6 | 5. [php设计模式(五)抽象工厂模式](https://baijunyao.com/article/164)
7 | 6. [php设计模式(六)使用简单工厂来优化抽象工厂模式](https://baijunyao.com/article/165)
8 | 7. [php设计模式(七)使用反射来优化抽象工厂模式](https://baijunyao.com/article/166)
9 | 8. [php设计模式(八)原型模式](https://baijunyao.com/article/167)
10 | 9. [php设计模式(九)类适配器模式](https://baijunyao.com/article/168)
11 | 10. [php设计模式(十)对象适配器模式](https://baijunyao.com/article/169)
12 | 11. [php设计模式(十一)桥接模式](https://baijunyao.com/article/170)
13 | 12. [php设计模式(十二)装饰模式](https://baijunyao.com/article/172)
14 | 13. [php设计模式(十三)透明组合模式](https://baijunyao.com/article/174)
15 | 14. [php设计模式(十四)安全组合模式](https://baijunyao.com/article/175)
16 | 15. [php设计模式(十五)外观模式](https://baijunyao.com/article/176)
17 | 16. [php设计模式(十六)享元模式](https://baijunyao.com/article/177)
18 | 17. [php设计模式(十七)代理模式](https://baijunyao.com/article/178)
19 | 18. [php设计模式(十八)模板方法模式](https://baijunyao.com/article/179)
20 | 19. [php设计模式(十九)命令模式](https://baijunyao.com/article/182)
21 | 20. [php设计模式(二十)迭代器模式](https://baijunyao.com/article/183)
22 | 21. [php设计模式(二十一)观察者模式](https://baijunyao.com/article/184)
23 |
24 | ### 目录
25 | - [单例模式](https://github.com/baijunyao/design-patterns/tree/master/singleton)
26 | - [简单工厂模式](https://github.com/baijunyao/design-patterns/tree/master/SimpleFactory)
27 | - [工厂方法模式](https://github.com/baijunyao/design-patterns/tree/master/FactoryMethod)
28 | - [抽象工厂模式](https://github.com/baijunyao/design-patterns/tree/master/AbstractFactory)
29 | - [使用简单工厂来优化抽象工厂模式](https://github.com/baijunyao/design-patterns/tree/master/AbstractFactoryWithSimpleFactory)
30 | - [使用反射来优化抽象工厂模式](https://github.com/baijunyao/design-patterns/tree/master/AbstractFactoryWithReflection)
31 | - [原型模式](https://github.com/baijunyao/design-patterns/tree/master/Prototype)
32 | - [类适配器模式](https://github.com/baijunyao/design-patterns/tree/master/ClassAdapter)
33 | - [对象适配器模式](https://github.com/baijunyao/design-patterns/tree/master/ObjectAdapter)
34 | - [桥接模式](https://github.com/baijunyao/design-patterns/tree/master/Bridge)
35 | - [装饰模式](https://github.com/baijunyao/design-patterns/tree/master/Decorator)
36 | - [透明组合模式](https://github.com/baijunyao/design-patterns/tree/master/TransparentComposite)
37 | - [安全组合模式](https://github.com/baijunyao/design-patterns/tree/master/SafeComposite)
38 | - [外观模式](https://github.com/baijunyao/design-patterns/tree/master/Facade)
39 | - [享元模式](https://github.com/baijunyao/design-patterns/tree/master/Flyweight)
40 | - [代理模式](https://github.com/baijunyao/design-patterns/tree/master/Proxy)
41 | - [模板方法模式](https://github.com/baijunyao/design-patterns/tree/master/Template)
42 | - [命令模式](https://github.com/baijunyao/design-patterns/tree/master/Command)
43 | - [迭代器模式](https://github.com/baijunyao/design-patterns/tree/master/Iterator)
44 | - [观察者模式](https://github.com/baijunyao/design-patterns/tree/master/Observer)
45 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 设计模式-白俊遥
6 |
7 |
8 | 文章
9 |
10 | - php设计模式(一)序言
11 | - php设计模式(二)单例模式
12 | - php设计模式(三)简单工厂模式
13 | - php设计模式(四)工厂方法模式
14 | - php设计模式(五)抽象工厂模式
15 | - php设计模式(六)使用简单工厂来优化抽象工厂模式
16 | - php设计模式(七)使用反射来优化抽象工厂模式
17 | - php设计模式(八)原型模式
18 | - php设计模式(九)类适配器模式
19 | - php设计模式(十)对象适配器模式
20 | - php设计模式(十一)桥接模式
21 | - php设计模式(十二)装饰模式
22 | - php设计模式(十三)透明组合模式
23 | - php设计模式(十四)安全组合模式
24 | - php设计模式(十五)外观模式
25 | - php设计模式(十六)享元模式
26 | - php设计模式(十七)代理模式
27 | - php设计模式(十八)代理模式
28 | - php设计模式(十九)命令模式
29 | - php设计模式(二十)迭代器模式
30 | - php设计模式(二十一)观察者模式
31 |
32 | 目录
33 |
55 |
56 |
--------------------------------------------------------------------------------
/vendor/composer/ClassLoader.php:
--------------------------------------------------------------------------------
1 |
7 | * Jordi Boggiano
8 | *
9 | * For the full copyright and license information, please view the LICENSE
10 | * file that was distributed with this source code.
11 | */
12 |
13 | namespace Composer\Autoload;
14 |
15 | /**
16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17 | *
18 | * $loader = new \Composer\Autoload\ClassLoader();
19 | *
20 | * // register classes with namespaces
21 | * $loader->add('Symfony\Component', __DIR__.'/component');
22 | * $loader->add('Symfony', __DIR__.'/framework');
23 | *
24 | * // activate the autoloader
25 | * $loader->register();
26 | *
27 | * // to enable searching the include path (eg. for PEAR packages)
28 | * $loader->setUseIncludePath(true);
29 | *
30 | * In this example, if you try to use a class in the Symfony\Component
31 | * namespace or one of its children (Symfony\Component\Console for instance),
32 | * the autoloader will first look for the class under the component/
33 | * directory, and it will then fallback to the framework/ directory if not
34 | * found before giving up.
35 | *
36 | * This class is loosely based on the Symfony UniversalClassLoader.
37 | *
38 | * @author Fabien Potencier
39 | * @author Jordi Boggiano
40 | * @see http://www.php-fig.org/psr/psr-0/
41 | * @see http://www.php-fig.org/psr/psr-4/
42 | */
43 | class ClassLoader
44 | {
45 | // PSR-4
46 | private $prefixLengthsPsr4 = array();
47 | private $prefixDirsPsr4 = array();
48 | private $fallbackDirsPsr4 = array();
49 |
50 | // PSR-0
51 | private $prefixesPsr0 = array();
52 | private $fallbackDirsPsr0 = array();
53 |
54 | private $useIncludePath = false;
55 | private $classMap = array();
56 | private $classMapAuthoritative = false;
57 | private $missingClasses = array();
58 | private $apcuPrefix;
59 |
60 | public function getPrefixes()
61 | {
62 | if (!empty($this->prefixesPsr0)) {
63 | return call_user_func_array('array_merge', $this->prefixesPsr0);
64 | }
65 |
66 | return array();
67 | }
68 |
69 | public function getPrefixesPsr4()
70 | {
71 | return $this->prefixDirsPsr4;
72 | }
73 |
74 | public function getFallbackDirs()
75 | {
76 | return $this->fallbackDirsPsr0;
77 | }
78 |
79 | public function getFallbackDirsPsr4()
80 | {
81 | return $this->fallbackDirsPsr4;
82 | }
83 |
84 | public function getClassMap()
85 | {
86 | return $this->classMap;
87 | }
88 |
89 | /**
90 | * @param array $classMap Class to filename map
91 | */
92 | public function addClassMap(array $classMap)
93 | {
94 | if ($this->classMap) {
95 | $this->classMap = array_merge($this->classMap, $classMap);
96 | } else {
97 | $this->classMap = $classMap;
98 | }
99 | }
100 |
101 | /**
102 | * Registers a set of PSR-0 directories for a given prefix, either
103 | * appending or prepending to the ones previously set for this prefix.
104 | *
105 | * @param string $prefix The prefix
106 | * @param array|string $paths The PSR-0 root directories
107 | * @param bool $prepend Whether to prepend the directories
108 | */
109 | public function add($prefix, $paths, $prepend = false)
110 | {
111 | if (!$prefix) {
112 | if ($prepend) {
113 | $this->fallbackDirsPsr0 = array_merge(
114 | (array) $paths,
115 | $this->fallbackDirsPsr0
116 | );
117 | } else {
118 | $this->fallbackDirsPsr0 = array_merge(
119 | $this->fallbackDirsPsr0,
120 | (array) $paths
121 | );
122 | }
123 |
124 | return;
125 | }
126 |
127 | $first = $prefix[0];
128 | if (!isset($this->prefixesPsr0[$first][$prefix])) {
129 | $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130 |
131 | return;
132 | }
133 | if ($prepend) {
134 | $this->prefixesPsr0[$first][$prefix] = array_merge(
135 | (array) $paths,
136 | $this->prefixesPsr0[$first][$prefix]
137 | );
138 | } else {
139 | $this->prefixesPsr0[$first][$prefix] = array_merge(
140 | $this->prefixesPsr0[$first][$prefix],
141 | (array) $paths
142 | );
143 | }
144 | }
145 |
146 | /**
147 | * Registers a set of PSR-4 directories for a given namespace, either
148 | * appending or prepending to the ones previously set for this namespace.
149 | *
150 | * @param string $prefix The prefix/namespace, with trailing '\\'
151 | * @param array|string $paths The PSR-4 base directories
152 | * @param bool $prepend Whether to prepend the directories
153 | *
154 | * @throws \InvalidArgumentException
155 | */
156 | public function addPsr4($prefix, $paths, $prepend = false)
157 | {
158 | if (!$prefix) {
159 | // Register directories for the root namespace.
160 | if ($prepend) {
161 | $this->fallbackDirsPsr4 = array_merge(
162 | (array) $paths,
163 | $this->fallbackDirsPsr4
164 | );
165 | } else {
166 | $this->fallbackDirsPsr4 = array_merge(
167 | $this->fallbackDirsPsr4,
168 | (array) $paths
169 | );
170 | }
171 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172 | // Register directories for a new namespace.
173 | $length = strlen($prefix);
174 | if ('\\' !== $prefix[$length - 1]) {
175 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176 | }
177 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
179 | } elseif ($prepend) {
180 | // Prepend directories for an already registered namespace.
181 | $this->prefixDirsPsr4[$prefix] = array_merge(
182 | (array) $paths,
183 | $this->prefixDirsPsr4[$prefix]
184 | );
185 | } else {
186 | // Append directories for an already registered namespace.
187 | $this->prefixDirsPsr4[$prefix] = array_merge(
188 | $this->prefixDirsPsr4[$prefix],
189 | (array) $paths
190 | );
191 | }
192 | }
193 |
194 | /**
195 | * Registers a set of PSR-0 directories for a given prefix,
196 | * replacing any others previously set for this prefix.
197 | *
198 | * @param string $prefix The prefix
199 | * @param array|string $paths The PSR-0 base directories
200 | */
201 | public function set($prefix, $paths)
202 | {
203 | if (!$prefix) {
204 | $this->fallbackDirsPsr0 = (array) $paths;
205 | } else {
206 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207 | }
208 | }
209 |
210 | /**
211 | * Registers a set of PSR-4 directories for a given namespace,
212 | * replacing any others previously set for this namespace.
213 | *
214 | * @param string $prefix The prefix/namespace, with trailing '\\'
215 | * @param array|string $paths The PSR-4 base directories
216 | *
217 | * @throws \InvalidArgumentException
218 | */
219 | public function setPsr4($prefix, $paths)
220 | {
221 | if (!$prefix) {
222 | $this->fallbackDirsPsr4 = (array) $paths;
223 | } else {
224 | $length = strlen($prefix);
225 | if ('\\' !== $prefix[$length - 1]) {
226 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227 | }
228 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
230 | }
231 | }
232 |
233 | /**
234 | * Turns on searching the include path for class files.
235 | *
236 | * @param bool $useIncludePath
237 | */
238 | public function setUseIncludePath($useIncludePath)
239 | {
240 | $this->useIncludePath = $useIncludePath;
241 | }
242 |
243 | /**
244 | * Can be used to check if the autoloader uses the include path to check
245 | * for classes.
246 | *
247 | * @return bool
248 | */
249 | public function getUseIncludePath()
250 | {
251 | return $this->useIncludePath;
252 | }
253 |
254 | /**
255 | * Turns off searching the prefix and fallback directories for classes
256 | * that have not been registered with the class map.
257 | *
258 | * @param bool $classMapAuthoritative
259 | */
260 | public function setClassMapAuthoritative($classMapAuthoritative)
261 | {
262 | $this->classMapAuthoritative = $classMapAuthoritative;
263 | }
264 |
265 | /**
266 | * Should class lookup fail if not found in the current class map?
267 | *
268 | * @return bool
269 | */
270 | public function isClassMapAuthoritative()
271 | {
272 | return $this->classMapAuthoritative;
273 | }
274 |
275 | /**
276 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277 | *
278 | * @param string|null $apcuPrefix
279 | */
280 | public function setApcuPrefix($apcuPrefix)
281 | {
282 | $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
283 | }
284 |
285 | /**
286 | * The APCu prefix in use, or null if APCu caching is not enabled.
287 | *
288 | * @return string|null
289 | */
290 | public function getApcuPrefix()
291 | {
292 | return $this->apcuPrefix;
293 | }
294 |
295 | /**
296 | * Registers this instance as an autoloader.
297 | *
298 | * @param bool $prepend Whether to prepend the autoloader or not
299 | */
300 | public function register($prepend = false)
301 | {
302 | spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303 | }
304 |
305 | /**
306 | * Unregisters this instance as an autoloader.
307 | */
308 | public function unregister()
309 | {
310 | spl_autoload_unregister(array($this, 'loadClass'));
311 | }
312 |
313 | /**
314 | * Loads the given class or interface.
315 | *
316 | * @param string $class The name of the class
317 | * @return bool|null True if loaded, null otherwise
318 | */
319 | public function loadClass($class)
320 | {
321 | if ($file = $this->findFile($class)) {
322 | includeFile($file);
323 |
324 | return true;
325 | }
326 | }
327 |
328 | /**
329 | * Finds the path to the file where the class is defined.
330 | *
331 | * @param string $class The name of the class
332 | *
333 | * @return string|false The path if found, false otherwise
334 | */
335 | public function findFile($class)
336 | {
337 | // class map lookup
338 | if (isset($this->classMap[$class])) {
339 | return $this->classMap[$class];
340 | }
341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342 | return false;
343 | }
344 | if (null !== $this->apcuPrefix) {
345 | $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346 | if ($hit) {
347 | return $file;
348 | }
349 | }
350 |
351 | $file = $this->findFileWithExtension($class, '.php');
352 |
353 | // Search for Hack files if we are running on HHVM
354 | if (false === $file && defined('HHVM_VERSION')) {
355 | $file = $this->findFileWithExtension($class, '.hh');
356 | }
357 |
358 | if (null !== $this->apcuPrefix) {
359 | apcu_add($this->apcuPrefix.$class, $file);
360 | }
361 |
362 | if (false === $file) {
363 | // Remember that this class does not exist.
364 | $this->missingClasses[$class] = true;
365 | }
366 |
367 | return $file;
368 | }
369 |
370 | private function findFileWithExtension($class, $ext)
371 | {
372 | // PSR-4 lookup
373 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374 |
375 | $first = $class[0];
376 | if (isset($this->prefixLengthsPsr4[$first])) {
377 | $subPath = $class;
378 | while (false !== $lastPos = strrpos($subPath, '\\')) {
379 | $subPath = substr($subPath, 0, $lastPos);
380 | $search = $subPath.'\\';
381 | if (isset($this->prefixDirsPsr4[$search])) {
382 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383 | foreach ($this->prefixDirsPsr4[$search] as $dir) {
384 | if (file_exists($file = $dir . $pathEnd)) {
385 | return $file;
386 | }
387 | }
388 | }
389 | }
390 | }
391 |
392 | // PSR-4 fallback dirs
393 | foreach ($this->fallbackDirsPsr4 as $dir) {
394 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395 | return $file;
396 | }
397 | }
398 |
399 | // PSR-0 lookup
400 | if (false !== $pos = strrpos($class, '\\')) {
401 | // namespaced class name
402 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404 | } else {
405 | // PEAR-like class name
406 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407 | }
408 |
409 | if (isset($this->prefixesPsr0[$first])) {
410 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411 | if (0 === strpos($class, $prefix)) {
412 | foreach ($dirs as $dir) {
413 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414 | return $file;
415 | }
416 | }
417 | }
418 | }
419 | }
420 |
421 | // PSR-0 fallback dirs
422 | foreach ($this->fallbackDirsPsr0 as $dir) {
423 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424 | return $file;
425 | }
426 | }
427 |
428 | // PSR-0 include paths.
429 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430 | return $file;
431 | }
432 |
433 | return false;
434 | }
435 | }
436 |
437 | /**
438 | * Scope isolated include.
439 | *
440 | * Prevents access to $this/self from included files.
441 | */
442 | function includeFile($file)
443 | {
444 | include $file;
445 | }
446 |
--------------------------------------------------------------------------------