【问题标题】:Is there any Design Pattern for calling object methods statically是否有任何静态调用对象方法的设计模式
【发布时间】:2015-04-03 09:55:27
【问题描述】:

基本上我正在尝试制作一个用于处理文件和目录的库。

我们的想法是为FileFindingFileReadingFileWriting 等设置单独的类。

我正在尝试搜索是否有任何设计模式可以实现类似:

只有一次课可以说

<?php namespace vendor/FileHandler;

 class FileHandler {}

现在在图书馆里我有特定的类可以说

<?php namespace vendor/FileHandler;

class FileFinder 
{
     /**
     * Find files by their types
     * 
     * @param string $path path to find files in.
     * @param mixed $type string or array of file type/types (extensions).
     * @return array array of file names.
     */
    public function findFilesByType($path, $type)
    {
        // do logic here.
        return $files;
    }
}

现在我希望我的图书馆用户使用主类FileHandler::findFilesByType(); 调用FileFinder::findFilesByType()

请注意:FileFinder::findFilesByType() 不是静态方法,但我希望将其用作class FileHanlder 的静态方法

更新: 我上面问的问题似乎类似于 Laravel 的 Facade 模式。但他们的实施超出了我的想象。即使我不确定 Facade 模式是否会这样做。

【问题讨论】:

  • @SagarNaliyapara 你的链接没有回答我的问题。
  • FileFinder 应该依赖于 FileHandler,但是静态调用是不可能的。所以另一种方法是使用 FileFinder 扩展抽象 FileHandler。然后你可以调用FileHandler的方法,用户不能直接使用抽象类......但我不确定这是一个好习惯......
  • 去掉了OOP标签,因为你想做的与OOP相反。

标签: php algorithm design-patterns static


【解决方案1】:

外观应该保留每个类的静态实例,该实例提供您自己想要转发给库用户的功能。

在门面的静态方法中,利用上述对象并将方法调用转发给它们。 仅使用这种方法,如果您转发的对象是无状态的, 否则,您必须在外观方法中创建适当的对象,以免在方法调用之间传播状态信息。

下面是一个java中的小例子,但你会明白的

public class Facade {
    private static final HashComputer computer = new HashComputer();

    // since this operation changes state of accumulator,
    // it has to create one on each invocation
    public static List<String> accumulate(String... args) {
        Accumulator acc = new Accumulator();
        for (String arg : args)
            acc.add(arg);

        return acc.collect();
    }

    // this operation does not change state of the object it delegates to,
    // so there is no need to create a new instance on every invocation
    public static int computeHash(String s) {
        return computer.hashFor(s);
    }

    // has stateless instances
    private static class HashComputer {
        public int hashFor(String s) {
            return s.hashCode();
        }
    }

    // instances have state depending on state of list
    private static class Accumulator {
        List<String> arguments = new ArrayList<String>();
        public void add(String s) {
            arguments.add(s);
        }
        public List<String> collect() {
            return Collections.unmodifiableList(arguments);
        }
    }
}

严格来说,这种实现外观的确切方式恰好适合您的需求。外观不必是具有静态方法的实用程序类,它也可以是类的实例。

外观设计模式背后的原则是从一组负责某些常见功能的类(或整个层)的内在函数中抽象出来,封装操作并授予对它们的简单访问权限,也许是高级访问权限.


正如@PeeHaa 在他的评论中提到的那样,这种静态外观方法确实不是 OOP 意义上的,因为违反了law of demeter,它说:

Class 类的方法 method 应该只调用方法

  • Class
  • method 创建的对象
  • 关于method的论点
  • 关于Class的实例变量

从这个意义上说,您不要使用带有静态方法的外观,因为您调用的是类上的方法,而不是它的实例。

【讨论】:

  • 谢谢我明白了这个概念。您能否就@PeeHaa 在他的评论中提到的这种方法如何反对 OOP 发表评论。我只想说清楚,然后再进一步。谢谢
【解决方案2】:

你可以使用__callStatic

<?php

namespace vendor/FileHandler;

class FileHandler {

/**  PHP >= 5.3.0  */
public static function __callStatic($name, $arguments) {

  if($name == 'findFilesByType') {
    $obj = new FileFinder();
    return $obj->findFilesByType(implode(', ', $arguments));      
  }   
}
}
?>

呼叫:

FileHandler::FileHandler('/files', 'pdf');

了解更多:

http://php.net/manual/en/language.oop5.overloading.php#object.callstatic

【讨论】:

  • 这似乎是一个可行的解决方案,但我有 100 种方法,分为 5 个类。做这么多if 太长了。你怎么看?
  • @RaheelKhan 你可以把我的回答和Reflection结合起来php.net/ReflectionClass我累了,在我的国家是早上6点20分,我整晚都没有睡
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-13
  • 2014-01-17
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多