工厂方法模式

This commit is contained in:
cloud 2022-04-15 04:27:05 +08:00
parent c6b8e1af82
commit e5a380573b
24 changed files with 4606 additions and 49 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
.idea
.idea
/vendor/

1
.phpunit.result.cache Normal file
View File

@ -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}}

View File

@ -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
# 学习顺序

18
Tests/StackTest.php Normal file
View File

@ -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));
}
}

View File

@ -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;

View File

@ -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();
/**
* 统一返回错误信息
*

8
bin/DesignInterface.php Normal file
View File

@ -0,0 +1,8 @@
<?php
namespace bin;
interface DesignInterface
{
}

25
composer.json Normal file
View File

@ -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"
}
}

4340
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
# 行为型

View File

@ -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('这个创建型');
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace demo\Creational\FactoryMethod;
interface Logger
{
// 要实现的方法
public function log(string $message);
}

View File

@ -0,0 +1,8 @@
<?php
namespace demo\Creational\FactoryMethod;
interface LoggerFactory
{
public function createLogger() : Logger;
}

View File

@ -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);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace demo\Creational\FactoryMethod;
class StdoutLogger implements Logger
{
public function log(string $message)
{
echo $message;
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace demo\Creational\FactoryMethod;
class StdoutLoggerFactory implements LoggerFactory
{
public function createLogger() : Logger
{
return new StdoutLogger();
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1 @@
# 创建型

1
demo/More/README.md Normal file
View File

@ -0,0 +1 @@
# 更多其他类型

View File

@ -0,0 +1 @@
# 结构型

View File

@ -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);

15
psalm.xml Normal file
View File

@ -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>