Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 抽象、接口和设计模式_Php_Design Patterns - Fatal编程技术网

Php 抽象、接口和设计模式

Php 抽象、接口和设计模式,php,design-patterns,Php,Design Patterns,我用PHP开发了很多年,在PHP5中使用了一个小型的自制MVC框架,从未使用PHP5.2+的优点 我知道什么是抽象类,什么是接口,什么是名称空间,什么是设计模式,但我总是想到一件简单的事情,什么时候最好使用接口、抽象类或模式设计 在我的框架中,我有一个Core with Router类,路由器调用Core,Core加载控制器,并使用路由器变量调用控制器函数 控制器扩展了内核,可以使用内核中的一个函数来加载“组件”,这个函数是一个简单的单例模式,使用一个静态数组,来实例我从控制器或其他组件“调用”

我用PHP开发了很多年,在PHP5中使用了一个小型的自制MVC框架,从未使用PHP5.2+的优点

我知道什么是抽象类,什么是接口,什么是名称空间,什么是设计模式,但我总是想到一件简单的事情,什么时候最好使用接口、抽象类或模式设计

在我的框架中,我有一个Core with Router类,路由器调用Core,Core加载控制器,并使用路由器变量调用控制器函数

控制器扩展了内核,可以使用内核中的一个函数来加载“组件”,这个函数是一个简单的单例模式,使用一个静态数组,来实例我从控制器或其他组件“调用”的类,速度非常快,占用的内存很低,但有更好的方法吗

在控制器或组件中,我写入:

function example() {

    $this->loadComponent(array('Cache', 'Template', 'Email'));
    $this->Email->X();

}
这将创建实例(如果不存在,如果存在,则返回指向实例的指针“&”,而不是副本),并设置控制器或组件以允许使用$This->ComponentName->XXXX

函数使用$this->loadComponent(数组('Cache'=>'Cache2')创建一个副本;如果我需要一些副本,而不是相同的。(例如,多个DB连接)

我认为这可以做得更好

现在我陷入了另一个设计问题:

我有一个缓存类,这个类有3种方式的缓存,Memcache,Redis或文件缓存

是一个简单的类(没有抽象或接口),缓存函数位于单独的类CacheMem、CacheRes、CacheFile中,当使用loadComponent加载缓存类时,该类读取定义配置,并使用此定义执行以下操作:

function __construct() {

    private $engine;

    switch (CONFIG_CACHE_TYPE) {

        case "MEM":
        $class = 'CacheMem'
        require ('Components'.DS.$class.'.php');
        $this->engine = new CacheMem();

        break;

        case "RES":
        $class = 'CacheRedis'
        require ('Components'.DS.$class.'.php');
        $this->engine = new CacheRedis();

        break;

        default:
        $class = 'CacheFile';
        require ('Components'.DS.$class.'.php');
        $this->engine = new Cachefile();
        break;

    }

}

function read($key) {
    $this->engine->read($key);
}

function write($key, $value, $time=3800) {
    $this->engine->write($key, $value, $time=3800);
}
有没有更好的办法解决这个问题?这是一个简单的问题,但我有一件事需要解决:我需要使用“cache”名称加载cache类,而不是CacheMem、CacheFile或CacheRes

我尝试使用抽象类缓存,并使用Mem、Res或File进行扩展,但我需要在缓存类中引用子类,因为我想使用“Cache”而不是“CacheXXX”,我知道这是错误的


您建议如何解决这个问题?

在oop中有很多方法可以解决问题:)

控制器扩展内核,并可以使用内核中的函数

如果您不知道是否要扩展类,请扪心自问:控制器是核心吗?希望不是这样。如果您的控制器需要一个核心,那么将其传递给构造函数。原因是1。隐藏实现,意味着“注入”核心并在内部使用隐藏通过控制器对核心的访问,2。只有一个扩展是允许的,所以请谨慎和智能地使用它,例如,汽车或自行车是一辆汽车,因此扩展可能是可以的,如果我们的汽车有一些汽车和自行车使用的实现,但可能汽车只是一个没有实现的接口

这将创建实例(如果不存在,如果存在,则返回指向实例的指针“&”,而不是副本)

PHP使用的是引用计数变量。返回对象意味着返回引用。要复制对象,PHP中有
clone
操作符

开关(配置缓存类型)

什么是配置缓存类型?如果它是在调用构造之前定义的常量,这是一个坏主意。只需将其作为变量传递。请记住,您使用的一些开关箱违反了开闭原则,这是一种糟糕的设计

switch(...) {
    case ...:
     ... = new A();
    case ...:
     ... = new B();
    case ...:
     ... = new C();
    ...
}
在您的特殊情况下,我将创建一个接口CacheInterface,让您的类实现
,然后将
缓存接口
传递到需要缓存的地方

根据经验:一个好的设计不需要
扩展
抽象
。oop初学者,但也有一些高级程序员认为,oop很酷,可以通过扩展很多类来重用他们的代码。理解
扩展
抽象
并不意味着你必须尽可能地使用它们

//编辑:你问了两个问题,我忽略了第一个。检查DI(依赖注入)作为创造性模式