Wake Me Up When September Ends.

A wanderer capable of grasping the beauty of the grass, with a heart full of ancient charm, and a fondness for playful wit. Those who understand my words are knowledgeable individuals; those who decipher my code truly comprehend the essence. I am a wandering code swordsman, carrying my skills and riding freely through the digital world.

💫设计模式-工厂模式

工厂模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。

需求的场景

这种模式在面试中经常会被问到,很多面试题的答案会表示该模式经常用于框架的db或cache组件设计。

假设你所在项目组在开发某个项目中,使用了多种缓存数据源,比如有内存,redis,本地文件。目前每次根据不同场景使用不同类型缓存,需要实例化不同缓存实例进行操作,比较繁琐。项目组开发人员希望统一调用缓存入口,简化缓存调用心智负担。

如何解决

  1. 定义cache工厂类(父类)和依赖类
  2. 编写各个类型cache子类
  3. cache工厂类创建调用

实现

这边实现使用PHP代码作为演示,其他oop语言逻辑类似。

😼1.定义cache工厂类(父类)和依赖类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// config 配置类 用于缓存实例化依赖配置数据
class Config
{
private string $host; //连接host

private string $dbName;// 数据库名称

private string $password;// 密码

private string $userName;// 用户名

private int $port; //端口

public function getHost(): string
{
return $this->host;
}

public function setHost(string $host): static
{
$this->host = $host;
return $this;
}

public function getDbName(): string
{
return $this->dbName;
}

public function setDbName(string $dbName): static
{
$this->dbName = $dbName;
return $this;
}

public function getPassword(): string
{
return $this->password;
}

public function setPassword(string $password): static
{
$this->password = $password;
return $this;
}

public function getUserName(): string
{
return $this->userName;
}

public function setUserName(string $userName): static
{
$this->userName = $userName;
return $this;
}


public function getPort(): string
{
return $this->port;
}

public function setPort(int $port): static
{
$this->port = $port;
return $this;
}
}

// 工厂类

class Cache
{
protected Config $config;

public function __construct(Config $config)
{
//通过构造注入Config依赖
$this->config = $config;
}

public static create(string $cache)
{
//创建实例
return new $cache($this->config);
}


}


😸2.编写各个类型cache子类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// redis 
class Redis extends Cache
{

private Redis $redis

public function __construct(Config $config)
{
parent::__construct(Config $config);

$this->connect()
}

protected function connect()
{
//根据Config进行缓存连接
$this->redis = new \Redis();

// 连接 Redis 服务器
$this->redis->connect($this->config->getHost() , $this->config->getPort() ?? 6379);

// 可选:设置 Redis 密码
$this->redis->auth($this->config->getPassword());

}

// 动态调用redis 方法
public function __call($method, ...$arguments) {
call_user_func([$this->redis, $method], ...$arguments);
}


}

//内存
class Memory extends Cache
{

public function __construct(Config $config)
{

parent::__construct(Config $config);

}


}

//文件
class File extends Cache
{

private string $cachePath = '/dev/logs/'

public function __construct(Config $config)
{
parent::__construct(Config $config);

}


}

😺3.cache工厂类创建调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class  Demo
{
public function run()
{
$config = (new Config())->setHost('localhost')
->setUserName('demo')
->setPassword('*****');

$cache = new Cache($config);
//创建redis cache实例
$redis = $cache->create(Redis::class);
//创建本地file cache实例
$file = $cache->create(File::class);
}
}