工厂方法模式
This commit is contained in:
parent
c6b8e1af82
commit
e5a380573b
|
|
@ -1 +1,2 @@
|
||||||
.idea
|
.idea
|
||||||
|
/vendor/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":1,"defects":{"demo\\Creational\\FactoryMethod\\tests\\FactoryMethodTest::testCanCreateStdoutLogging":4,"demo\\Creational\\FactoryMethod\\tests\\FactoryMethodTest::testCanCreateFileLogging":4,"demo\\Creational\\FactoryMethod\\tests\\StdoutLoggerTest::testCanCreateStdoutLogging":4,"demo\\Creational\\FactoryMethod\\tests\\StdoutLoggerTest::testCanCreateFileLogging":4,"demo\\Creational\\FactoryMethod\\tests\\StdoutLoggerTest::testLog":4,"demo\\Creational\\Singleton\\Tests\\SingletonTest::testUniqueness":4,"demo\\Structural\\DependencyInjection\\Tests\\DependencyInjectionTest::testDependencyInjection":4},"times":{"demo\\Creational\\FactoryMethod\\tests\\FactoryMethodTest::testCanCreateStdoutLogging":0.007,"demo\\Creational\\FactoryMethod\\tests\\FactoryMethodTest::testCanCreateFileLogging":0,"StackTest::testPushAndPop":0.004,"demo\\Creational\\FactoryMethod\\tests\\StdoutLoggerTest::testCanCreateStdoutLogging":0.005,"demo\\Creational\\FactoryMethod\\tests\\StdoutLoggerTest::testCanCreateFileLogging":0,"demo\\Creational\\FactoryMethod\\tests\\StdoutLoggerTest::testLog":0.004,"demo\\Creational\\Singleton\\Tests\\SingletonTest::testUniqueness":0.005,"demo\\Structural\\DependencyInjection\\Tests\\DependencyInjectionTest::testDependencyInjection":0.007}}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
### PHP PSR 标准规范:https://learnku.com/docs/psr
|
### PHP PSR 标准规范:https://learnku.com/docs/psr
|
||||||
### PHP 设计模式全集:https://learnku.com/docs/php-design-patterns/2018
|
### PHP 设计模式全集:https://learnku.com/docs/php-design-patterns/2018
|
||||||
### PHP 设计模式全集:https://laravelacademy.org/books/php-design-pattern
|
### PHP 设计模式全集:https://laravelacademy.org/books/php-design-pattern
|
||||||
|
### PHPunit 文档:https://phpunit.readthedocs.io/zh_CN/latest/assertions.html
|
||||||
### 环境PHP8.1.4
|
### 环境PHP8.1.4
|
||||||
|
|
||||||
# 学习顺序
|
# 学习顺序
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
class StackTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
public function testPushAndPop(): void
|
||||||
|
{
|
||||||
|
$stack = [];
|
||||||
|
$this->assertSame(0, count($stack));
|
||||||
|
|
||||||
|
$stack[] = 'foo';
|
||||||
|
$this->assertSame('foo', $stack[count($stack)-1]);
|
||||||
|
$this->assertSame(1, count($stack));
|
||||||
|
|
||||||
|
$this->assertSame('foo', array_pop($stack));
|
||||||
|
$this->assertSame(0, count($stack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -46,14 +46,12 @@ class Base
|
||||||
try {
|
try {
|
||||||
// 初始化类,再执行对应方法
|
// 初始化类,再执行对应方法
|
||||||
$class = $this->newClass($this->queryString);
|
$class = $this->newClass($this->queryString);
|
||||||
|
$designName = $class->designName;
|
||||||
|
echo "<pre class='sf-dump' style='font-size: large;background-color: transparent;padding: 30px 0px;'>$designName<a href='/' style='margin-left:20px;'><span style='color:green'>返回首页</span></a></pre>";
|
||||||
$class->main();
|
$class->main();
|
||||||
} catch (\ReflectionException $e) {
|
} catch (\ReflectionException $e) {
|
||||||
var_dump($e->getMessage());
|
var_dump($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "<div style='display: block;margin-top: 100px;'>
|
|
||||||
<a href='/'><span style='font-size: 24px; color:green'>返回首页</span></a>
|
|
||||||
</div>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -65,8 +63,8 @@ class Base
|
||||||
{
|
{
|
||||||
$li = '';
|
$li = '';
|
||||||
foreach ($this->dirFiles as $file) {
|
foreach ($this->dirFiles as $file) {
|
||||||
$newClass = $this->newClass($file);
|
|
||||||
$designUrl = '';
|
$designUrl = '';
|
||||||
|
$newClass = $this->newClass($file);
|
||||||
try {
|
try {
|
||||||
if (is_object($newClass)) {
|
if (is_object($newClass)) {
|
||||||
$designName = $newClass->designName;
|
$designName = $newClass->designName;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace bin;
|
namespace bin;
|
||||||
|
|
||||||
class Design
|
abstract class Design
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 对应设计模式名称
|
* 对应设计模式名称
|
||||||
|
|
@ -17,6 +17,33 @@ class Design
|
||||||
*/
|
*/
|
||||||
public string $designRefUrl;
|
public string $designRefUrl;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->designName = $this->setDesignName();
|
||||||
|
$this->designRefUrl = $this->setDesignRefUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置设计名称
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
abstract public function setDesignName() : string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置参考地址
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
abstract public function setDesignRefUrl() : string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入口方法
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
abstract public function main();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一返回错误信息
|
* 统一返回错误信息
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace bin;
|
||||||
|
|
||||||
|
interface DesignInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"name": "cloud/designmode",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"bin\\": "bin/",
|
||||||
|
"demo\\": "demo/",
|
||||||
|
"Cloud\\Designmode\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "b"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"require": {
|
||||||
|
"symfony/var-dumper": "6.1.x-dev",
|
||||||
|
"php-console/php-console": "dev-master",
|
||||||
|
"psalm/plugin-phpunit": "dev-master"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "9.x.x",
|
||||||
|
"vimeo/psalm": "5.x-dev"
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
||||||
|
# 行为型
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace demo\Creational\A;
|
|
||||||
|
|
||||||
use bin\Design;
|
|
||||||
|
|
||||||
class Run extends Design
|
|
||||||
{
|
|
||||||
public string $designName = "创建型";
|
|
||||||
public string $designRefUrl = '';
|
|
||||||
|
|
||||||
public function main()
|
|
||||||
{
|
|
||||||
var_dump('这个创建型');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace demo\Creational\FactoryMethod;
|
||||||
|
|
||||||
|
class FileLogger implements Logger
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private string $filePath;
|
||||||
|
|
||||||
|
public function __construct(string $filePath)
|
||||||
|
{
|
||||||
|
$this->filePath = $filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function log(string $message)
|
||||||
|
{
|
||||||
|
file_put_contents($this->filePath, $message . PHP_EOL, FILE_APPEND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace demo\Creational\FactoryMethod;
|
||||||
|
|
||||||
|
use JetBrains\PhpStorm\Pure;
|
||||||
|
|
||||||
|
class FileLoggerFactory implements LoggerFactory
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private string $filePath;
|
||||||
|
|
||||||
|
public function __construct(string $filePath)
|
||||||
|
{
|
||||||
|
$this->filePath = $filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createLogger() : Logger
|
||||||
|
{
|
||||||
|
return new FileLogger($this->filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace demo\Creational\FactoryMethod;
|
||||||
|
|
||||||
|
interface Logger
|
||||||
|
{
|
||||||
|
// 要实现的方法
|
||||||
|
public function log(string $message);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace demo\Creational\FactoryMethod;
|
||||||
|
|
||||||
|
interface LoggerFactory
|
||||||
|
{
|
||||||
|
public function createLogger() : Logger;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace demo\Creational\FactoryMethod;
|
||||||
|
|
||||||
|
class Run extends \bin\Design
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对比简单工厂模式的优点是,您可以将其子类用不同的方法来创建一个对象。
|
||||||
|
* 举一个简单的例子,这个抽象类可能只是一个接口。
|
||||||
|
* 这种模式是「真正」的设计模式, 因为他实现了 S.O.L.I.D 原则中「D」的 「依赖倒置」。
|
||||||
|
* 这意味着工厂方法模式取决于抽象类,而不是具体的类。 这是与简单工厂模式和静态工厂模式相比的优势。
|
||||||
|
*
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function setDesignName() : string
|
||||||
|
{
|
||||||
|
return '工厂方法模式(Factory Method)';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function setDesignRefUrl() : string
|
||||||
|
{
|
||||||
|
return 'https://learnku.com/docs/php-design-patterns/2018/FactoryMethod/1489';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function main()
|
||||||
|
{
|
||||||
|
(new StdoutLogger)->log('测试日志打印');
|
||||||
|
$loggerFactory = new StdoutLoggerFactory();
|
||||||
|
$logger = $loggerFactory->createLogger();
|
||||||
|
// 判断类型是否一样
|
||||||
|
dump(StdoutLogger::class instanceof $logger);
|
||||||
|
|
||||||
|
$loggerFactory = new FileLoggerFactory(sys_get_temp_dir());
|
||||||
|
$logger = $loggerFactory->createLogger();
|
||||||
|
dump(FileLogger::class instanceof $logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace demo\Creational\FactoryMethod;
|
||||||
|
|
||||||
|
class StdoutLogger implements Logger
|
||||||
|
{
|
||||||
|
|
||||||
|
public function log(string $message)
|
||||||
|
{
|
||||||
|
echo $message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace demo\Creational\FactoryMethod;
|
||||||
|
|
||||||
|
class StdoutLoggerFactory implements LoggerFactory
|
||||||
|
{
|
||||||
|
|
||||||
|
public function createLogger() : Logger
|
||||||
|
{
|
||||||
|
return new StdoutLogger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace demo\Creational\FactoryMethod\tests;
|
||||||
|
|
||||||
|
use demo\Creational\FactoryMethod\FileLogger;
|
||||||
|
use demo\Creational\FactoryMethod\FileLoggerFactory;
|
||||||
|
use demo\Creational\FactoryMethod\StdoutLogger;
|
||||||
|
use demo\Creational\FactoryMethod\StdoutLoggerFactory;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class FactoryMethodTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testCanCreateStdoutLogging()
|
||||||
|
{
|
||||||
|
$loggerFactory = new StdoutLoggerFactory();
|
||||||
|
$logger = $loggerFactory->createLogger();
|
||||||
|
// 断言变量属于给定类型
|
||||||
|
$this->assertInstanceOf(StdoutLogger::class, $logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanCreateFileLogging()
|
||||||
|
{
|
||||||
|
$loggerFactory = new FileLoggerFactory(sys_get_temp_dir());
|
||||||
|
$logger = $loggerFactory->createLogger();
|
||||||
|
// 断言变量属于给定类型
|
||||||
|
$this->assertInstanceOf(FileLogger::class, $logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
# 创建型
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
# 更多其他类型
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
# 结构型
|
||||||
26
index.php
26
index.php
|
|
@ -1,35 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
const ROOTDIR = __DIR__;
|
const ROOTDIR = __DIR__;
|
||||||
/**
|
|
||||||
* 输出字符串或数组
|
|
||||||
*
|
|
||||||
* @param string/array $vars 输出字符串或数组
|
|
||||||
* @param string $label 提示标题
|
|
||||||
* @param bool|string $return 是否有返回值
|
|
||||||
*/
|
|
||||||
function dump($vars, bool|string $return = false, string $label = '')
|
|
||||||
{
|
|
||||||
if (ini_get('html_errors')) {
|
|
||||||
$content = "<pre>\n";
|
|
||||||
if ($label != '') {
|
|
||||||
$content .= "<strong>{$label} :</strong>\n";
|
|
||||||
}
|
|
||||||
$content .= htmlspecialchars(print_r($vars, true), ENT_COMPAT, 'ISO-8859-1');
|
|
||||||
$content .= "\n</pre>\n";
|
|
||||||
} else {
|
|
||||||
$content = $label . " :\n" . print_r($vars, true);
|
|
||||||
}
|
|
||||||
echo $content;
|
|
||||||
if ($return) exit;
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
require ROOTDIR . '/vendor/autoload.php';
|
||||||
|
|
||||||
require ROOTDIR . '/bin/Psr4Autoload.php';
|
require ROOTDIR . '/bin/Psr4Autoload.php';
|
||||||
|
|
||||||
(new \bin\Psr4Autoload)->register();
|
(new \bin\Psr4Autoload)->register();
|
||||||
|
|
||||||
(new \bin\Base);
|
(new \bin\Base);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<psalm
|
||||||
|
errorLevel="1"
|
||||||
|
resolveFromConfigFile="true"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="https://getpsalm.org/schema/config"
|
||||||
|
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||||
|
>
|
||||||
|
<projectFiles>
|
||||||
|
<directory name="src"/>
|
||||||
|
<ignoreFiles>
|
||||||
|
<directory name="vendor"/>
|
||||||
|
</ignoreFiles>
|
||||||
|
</projectFiles>
|
||||||
|
<plugins><pluginClass class="Psalm\PhpUnitPlugin\Plugin"/></plugins></psalm>
|
||||||
Loading…
Reference in New Issue