工厂方法模式
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 设计模式全集:https://learnku.com/docs/php-design-patterns/2018
|
||||
### PHP 设计模式全集:https://laravelacademy.org/books/php-design-pattern
|
||||
### PHPunit 文档:https://phpunit.readthedocs.io/zh_CN/latest/assertions.html
|
||||
### 环境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));
|
||||
}
|
||||
}
|
10
bin/Base.php
10
bin/Base.php
|
@ -45,15 +45,13 @@ class Base
|
|||
{
|
||||
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();
|
||||
} catch (\ReflectionException $e) {
|
||||
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 = '';
|
||||
foreach ($this->dirFiles as $file) {
|
||||
$newClass = $this->newClass($file);
|
||||
$designUrl = '';
|
||||
$newClass = $this->newClass($file);
|
||||
try {
|
||||
if (is_object($newClass)) {
|
||||
$designName = $newClass->designName;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace bin;
|
||||
|
||||
class Design
|
||||
abstract class Design
|
||||
{
|
||||
/**
|
||||
* 对应设计模式名称
|
||||
|
@ -17,6 +17,33 @@ class Design
|
|||
*/
|
||||
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
|
||||
|
||||
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';
|
||||
|
||||
(new \bin\Psr4Autoload)->register();
|
||||
|
||||
(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