From 0ef4f6a1e49f84c3e358b92c7ccf1e3282f34e3a Mon Sep 17 00:00:00 2001 From: cloud Date: Wed, 13 Apr 2022 06:00:06 +0800 Subject: [PATCH] 0.1 --- .gitignore | 1 + .idea/.gitignore | 8 ++ .idea/designModeDemo.git.iml | 11 ++ .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 + README.md | 35 +++++- bin/Base.php | 139 ++++++++++++++++++++++ bin/Design.php | 29 +++++ bin/Psr4Autoload.php | 144 +++++++++++++++++++++++ demo/AbstractFactory/AbstractFactory.php | 35 ++++++ demo/AbstractFactory/JsonFactory.php | 37 ++++++ demo/AbstractFactory/Run.php | 14 +++ index.php | 35 ++++++ info.php | 3 + mode/Ceshi.php | 11 ++ 15 files changed, 514 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/designModeDemo.git.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 bin/Base.php create mode 100644 bin/Design.php create mode 100644 bin/Psr4Autoload.php create mode 100644 demo/AbstractFactory/AbstractFactory.php create mode 100644 demo/AbstractFactory/JsonFactory.php create mode 100644 demo/AbstractFactory/Run.php create mode 100644 index.php create mode 100644 info.php create mode 100644 mode/Ceshi.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/designModeDemo.git.iml b/.idea/designModeDemo.git.iml new file mode 100644 index 0000000..003c0be --- /dev/null +++ b/.idea/designModeDemo.git.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..47d3a0e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index b0bf8e1..d13551c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,34 @@ -# designModeDemo +# 设计模式演示 +### PHP 示例代码 https://github.com/DesignPatternsPHP/DesignPatternsPHP +### PHP PSR 标准规范:https://learnku.com/docs/psr +### PHP 设计模式全集:https://learnku.com/docs/php-design-patterns/2018 +### PHP 设计模式全集:https://laravelacademy.org/books/php-design-pattern +### 环境PHP8.1.4 -设计模式演示 \ No newline at end of file +# 学习顺序 +### PHP 学习顺序 https://www.cnblogs.com/guola/archive/2013/01/02/2841997.html +| 学习顺序 | 设计模式 | 常用程度 | 适用层次 | 引入时机 | 结构复杂度 | 变化 | 实现 | 体现的原则 | +| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |--------| +| 1 | 工厂方法模式(Factory Method) | 很常用 | 代码级 | 编码时 | 简单 | 子类的实例化 | 对象的创建工作延迟到子类 | 开闭原则 | +| 2 | 单例模式(Singleton) | 很常用 | 代码级、应用级 | 设计时、编码时 | 简单 | 唯一实例 | 封装对象产生的个数 | | +| 3 | 门面模式(Facade) | 很常用 | 应用级、构架级 | 设计时、编码时 | 简单 | 子系统的高层接口 | 封装子系统 | 开闭原则 | +| 4 | 模板方法模式(Template Method) | 很常用 | 代码级 | 编码时、重构时 | 简单 | 算法子步骤的变化 | 封装算法结构 | 依赖倒置原则 | +| 5 | 抽象工厂模式(Abstract Factory) | 比较常用 | 应用级 | 设计时 | 比较复杂 | 产品家族的扩展 | 封装产品族系列内容的创建 | 开闭原则 | +| 6 | 组合模式(Composite) | 比较常用 | 代码级 | 编码时、重构时 | 比较复杂 | 复杂对象接口的统一 | 统一复杂对象的接口 | 里氏代换原则 | +| 7 | 代理模式(Proxy) | 比较常用 | 应用级、构架级 | 设计时、编码时 | 简单 | 对象访问的变化 | 封装对象的访问过程 | 里氏代换原则 | +| 8 | 命令行模式(Command) | 比较常用 | 应用级 | 设计时、编码时 | 比较简单 | 请求的变化 | 封装行为对对象 | 开闭原则 | +| 9 | 观察者模式(Observer) | 比较常用 | 应用级、构架级 | 设计时、编码时 | 比较简单 | 通讯对象的变化 | 封装对象通知 | 开闭原则 | +| 10 | 策略模式(Strategy) | 比较常用 | 应用级 | 设计时 | 一般 | 算法的变化 | 封装算法 | 里氏代换原则 | +| 11 | 建造者模式(Builder) | 一般 | 代码级 | 编码时 | 一般 | 对象组建的变化 | 封装对象的组建过程 | 开闭原则 | +| 12 | 适配器模式(Adapter) | 一般 | 代码级 | 重构时 | 一般 | 对象接口的变化 | 接口的转换 | | +| 13 | 桥梁模式(Bridge) | 一般 | 代码级 | 设计时、编码时 | 一般 | 对象的多维度变化 | 分离接口以及实现 | 开闭原则 | +| 14 | 装饰模式(Decorator) | 一般 | 代码级 | 重构时 | 比较复杂 | 对象的组合职责 | 在稳定接口上扩展 | 开闭原则 | +| 15 | 迭代器模式(Iterator) | 一般 | 代码级、应用级 | 编码时、重构时 | 比较简单 | 对象内部集合的变化 | 封装对象内部集合的使用 | 单一职责原则 | +| 16 | 中介者模式(Mediator) | 一般 | 应用级、构架级 | 编码时、重构时 | 一般 | 对象交互的变化 | 封装对象间的交互 | 开闭原则 | +| 17 | 备忘录模式(Memento) | 一般 | 代码级 | 编码时 | 比较简单 | 状态的辅助保存 | 封装对象状态的变化 | 接口隔离原则 | +| 18 | 状态模式(State) | 一般 | 应用级 | 设计时、编码时 | 一般 | 对象状态的变化 | 封装与状态相关的行为 | 单一职责原则 | +| 19 | 访问者模式(Visitor) | 一般 | 应用级 | 设计时 | 比较复杂 | 对象操作变化 | 封装对象操作变化 | 开闭原则 | +| 20 | 原型模式(Prototype) | 不太常用 | 应用级 | 编码时、重构时 | 比较简单 | 实例化的类 | 封装对原型的拷贝 | 依赖倒置原则 | +| 21 | 享元模式(Flyweight) | 不太常用 | 代码级、应用级 | 设计时 | 一般 | 系统开销的优化 | 封装对象的获取 | | +| 22 | 责任链模式(Chain Of Responsibilities) | 不太常用 | 应用级、构架级 | 设计时、编码时 | 比较复杂 | 对象的请求过程 | 封装对象的责任范围 | | +| 23 | 解释器模式(Interpreter) | 不太常用 | 应用级 | 设计时 | 比较复杂 | 领域问题的变化 | 封装特定领域的变化 | | \ No newline at end of file diff --git a/bin/Base.php b/bin/Base.php new file mode 100644 index 0000000..e6013a2 --- /dev/null +++ b/bin/Base.php @@ -0,0 +1,139 @@ +queryString = $_SERVER['QUERY_STRING']) { + self::init(); + } else { + self::setDirFiles(); + self::outDirFiles(); + } + } + + /** + * 通过命名空间调用对应类方法 + * + * @return void + */ + public function init() + { + try { + // 初始化类,再执行对应方法 + $class = $this->newClass($this->queryString); + $class->main(); + } catch (\ReflectionException $e) { + var_dump($e->getMessage()); + } + + echo "
+ 返回首页 +
"; + } + + /** + * 输出可访问的命名空间路径到页面 + * + * @return void + */ + public function outDirFiles() + { + $li = ''; + foreach ($this->dirFiles as $file) { + $newClass = $this->newClass($file); + $designUrl = ''; + try { + if (is_object($newClass)) { + $designName = $newClass->designName; + $designUrl = $newClass->designRefUrl; + } else { + $designName = $newClass; + } + + } catch (\Exception $e) { + $designName = $e->getMessage(); + } + $nameUrl = $designUrl === '' ? $designName : "$designName"; + $li .= "
  • $nameUrl :$file
  • "; + } + echo "
    "; + } + + /** + * 根据命名空间获取对应对象 + * + * @param $namespace + * @return object|string + */ + protected function newClass($namespace) : object|string + { + try { + // 先获取类信息 + $reflect = new ReflectionClass($namespace); + // 初始化类,再执行对应方法 + return $reflect->newInstanceArgs(); + } catch (\ReflectionException $e) { + return $e->getMessage(); + } + } + + /** + * 设置demo所有可用文件 + * + * @return void + */ + protected function setDirFiles() + { + // $dir = ROOTDIR . DIRECTORY_SEPARATOR . $this->dir; + $this->scandir($this->dir); + } + + /** + * 循环目录 + * + * @param $dir + * @return void + */ + protected function scandir($dir) + { + $dirFiles = scandir($dir); + $oldDir = $dir . DIRECTORY_SEPARATOR; + foreach ($dirFiles as $file) { + if ($file !== '.' && $file !== '..') { + $newsDir = $oldDir . $file; + if (is_dir($newsDir)) { + $this->scandir($newsDir); + } elseif ($file === 'Run.php') { + // 这样可以屏蔽非入口 + $this->dirFiles[] = $oldDir . 'Run'; + } + } + } + } + +} \ No newline at end of file diff --git a/bin/Design.php b/bin/Design.php new file mode 100644 index 0000000..de513d7 --- /dev/null +++ b/bin/Design.php @@ -0,0 +1,29 @@ +addNamespace('bin', ROOTDIR . DIRECTORY_SEPARATOR . 'bin', true); + $this->addNamespace('demo', ROOTDIR . DIRECTORY_SEPARATOR . 'demo', true); + $this->addNamespace('mode', ROOTDIR . DIRECTORY_SEPARATOR . 'mode', true); + + } + + /** + * 为命名空间前缀添加一个基本目录 + * + * @param string $prefix 命名空间前缀。 + * @param string $base_dir 命名空间下类文件的基本目录 + * @param bool $prepend 如果为真,预先将基本目录入栈 + * 而不是后续追加;这将使得它会被首先搜索到。 + * @return void + */ + public function addNamespace(string $prefix, string $base_dir, bool $prepend = false) + { + // 规范化命名空间前缀 + $prefix = trim($prefix, '\\') . '\\'; + + // 规范化尾部文件分隔符 + $base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/'; + + // 初始化命名空间前缀数组 + if (isset($this->prefixes[ $prefix ]) === false) { + $this->prefixes[ $prefix ] = array(); + } + + // 保留命名空间前缀的基本目录 + if ($prepend) { + array_unshift($this->prefixes[ $prefix ], $base_dir); + } else { + array_push($this->prefixes[ $prefix ], $base_dir); + } + } + + /** + * 加载给定类名的类文件 + * + * @param string $class 合法类名 + * @return string|bool 成功时为已映射文件名,失败则为 false + */ + public function loadClass(string $class) + { + + // 当前命名空间前缀 + $prefix = $class; + + // 通过完整的命名空间类名反向映射文件名 + while (false !== $pos = strrpos($prefix, '\\')) { + + // 在前缀中保留命名空间分隔符 + $prefix = substr($class, 0, $pos + 1); + + // 其余的是相关类名 + $relative_class = substr($class, $pos + 1); + + // 尝试为前缀和相关类加载映射文件 + $mapped_file = $this->loadMappedFile($prefix, $relative_class); + if ($mapped_file) { + return $mapped_file; + } + + // 删除 strrpos() 下一次迭代的尾部命名空间分隔符 + $prefix = rtrim($prefix, '\\'); + } + + // 找不到映射文件 + return false; + } + + /** + * 为命名空间前缀和相关类加载映射文件。 + * + * @param string $prefix 命名空间前缀 + * @param string $relative_class 相关类 + * @return string|bool Boolean 无映射文件则为false,否则加载映射文件 + */ + protected function loadMappedFile(string $prefix, string $relative_class) + { + // 命名空间前缀是否存在任何基本目录 + if (isset($this->prefixes[ $prefix ]) === false) { + return false; + } + + // 通过基本目录查找命名空间前缀 + foreach ($this->prefixes[ $prefix ] as $base_dir) { + + // 用基本目录替换命名空间前缀 + // 用目录分隔符替换命名空间分隔符 + // 给相关的类名增加 .php 后缀 + $file = $base_dir + . str_replace('\\', '/', $relative_class) + . '.php'; + // 如果映射文件存在,则引入 + if ($this->requireFile($file)) { + // 搞定了 + return $file; + } + } + + // 找不到 + return false; + } + + /** + * 如果文件存在从系统中引入进来 + * + * @param string $file 引入文件 + * @return bool 文件存在则 true 否则 false + */ + protected function requireFile(string $file) : bool + { + if (file_exists($file)) { + require $file; + return true; + } + return false; + } + + +} \ No newline at end of file diff --git a/demo/AbstractFactory/AbstractFactory.php b/demo/AbstractFactory/AbstractFactory.php new file mode 100644 index 0000000..a1f24e5 --- /dev/null +++ b/demo/AbstractFactory/AbstractFactory.php @@ -0,0 +1,35 @@ +\n"; + if ($label != '') { + $content .= "{$label} :\n"; + } + $content .= htmlspecialchars(print_r($vars, true), ENT_COMPAT, 'ISO-8859-1'); + $content .= "\n\n"; + } else { + $content = $label . " :\n" . print_r($vars, true); + } + echo $content; + if ($return) exit; + return null; + +} + + +require ROOTDIR . '/bin/Psr4Autoload.php'; + +(new \bin\Psr4Autoload)->register(); + +(new \bin\Base); + diff --git a/info.php b/info.php new file mode 100644 index 0000000..f35a8ef --- /dev/null +++ b/info.php @@ -0,0 +1,3 @@ +