如何管理类配置并将其传播到更深层次

时间:2015-02-08 21:01:42

标签: php oop configuration encapsulation

我有一些需要互动的课程。每个类都有许多选项可以调整以获得一种或另一种行为。

注意:我没有测试代码,因此可能会出现语法错误)

注意2:我用PHP编写,但我想这个问题对每种OOP语言都有效)

<?php

class Process
{
    protected $element;
    protected $config;
    protected $default_config = array(
        'process_path' => '/bin/command',
        'default_output_path' => '/tmp/',
        'element_conf' => array()
    );

    public function __construct(array $config)
    {
        $this->config = $config;
        $element_config = array_key_exists('element_conf', $this->config) 
            ? $this->config['element_conf'] 
            : array();
        $this->element = new Element($element_config);
    }

    public function run()
    {
        $this->element->behave();

        // ...
    }

    // ...
}

class Element
{
    protected $type;
    protected $config;
    protected $default_config = array(
        'behaviour_type' => 'evil',
        'can_kill_people' => true
    );

    public function __construct(array $config)
    {
        $this->config = array_replace($this->default_config, $config);
        $this->type = $this->config['behaviour'];
    }

    public function behave()
    {
        // ...
    }

    // ....
}

class Config
{
    // get data from config file and makes it available with a static getter/setter
}

-------------------------------

$element_conf = array(
    'can_kill_people' => false
);
$process_conf = array(
    'default_output_path' => Config::get('default_output_path'),
    'element_conf' => $element_conf
);

$pr = new Process($process_conf);
$pr->run();

我想尽可能保持封装,所以我避免直接​​引用 Config 类的类(配置也可以从其他地方到达)。

我想收到你的想法:

  • 提供内部类的配置元素)。我想在顶层初始化它的配置 (在调用run()方法之前);但我找不到好的方式 元素的配置取决于来自的代码 过程

  • 为类提供配置的方法。如果在我的代码中传递/设置数组配置会更好吗? 我应该将每个设置作为构造函数参数传递,还是将其设置为 setter

  • 您是否将配置保留在受保护的属性中,作为数组或者您是否将每个相关设置分配给单个受保护/私有属性? (就像我为Element::type所做的那样)

  • 您管理课程配置的常用方法是什么?您是否也会尝试将课程存储在配置中?你喜欢阵列吗?或直接传递/设置参数/属性? (在我看来,这最后一种方法并不容易维护)。 或者甚至更好,是否存在专门针对此案例的设计模式

2 个答案:

答案 0 :(得分:1)

如果要通过Element对象对参数类进行参数化,则将Element对象作为参数传递,而不是将其参数作为参数传递。这种方法还强调Process类依赖于Element类,它现在不能立即从Process构造函数中看到。

对于数组配置 - 在我看来,使用数组很容易写,但实际上很难实际使用这个类,你怎么知道你的类支持哪些设置?我宁愿在构造函数中使用单个参数,也不使用具有已定义属性的单独配置类。

如果你将它包装在一些合理的公共界面中,你如何在类内部做事本身并不重要。你想要做的是保持尽可能多的私有东西,以便在必要时保持改变类的内部工作的能力,同时保持向后兼容的公共接口。另外请记住,受保护与公开几乎完全相同,因为您可以在不破坏向后兼容性的情况下进行更改,因为子类可以使用受保护的属性和方法。

最后一件事 - 如果你的类确实有许多参数可以改变它的行为,那么你可能应该考虑将这些不同的行为拆分为扩展基类或实现其接口的新类是否更好(无论如何)更适合你的情况。)

答案 1 :(得分:1)

没有最好的方法可以在全球范围内做某事,有最好的方法可以做你想要的(通用或不通用)(应用第一个断言:D)。

配置默认

配置项可能是强制性的,但应始终具有默认值(因此可能不是必需的)。 在我看来,提供默认值有两种方法:

  1. 陈述方式
    当您实例化配置对象时,您将提供所有默认值,但如果源不是动态的,则不可能有动态值。
  2. “内联”方式
    您在请求当前值时提供默认值。
  3. 但事实上,你可以使用自己的规则。

    使用这些规则,您可以为Element的配置提供默认值。但是它的当前配置可以作为子配置或其他来源提供......进程可以使用。

    声明性配置

    在源代码中,配置是声明性的,这意味着在开发它时,您知道配置存在且必须/可能/应该提供。因此,如果您使用具有私有元素的对象来存储您的配置值/格式或每个配置密钥的简单常量,则无关紧要。

    在我的框架中,所有配置都作为数组存储在Config类的受保护成员中。这是因为我需要通用性,但我不允许配置文件中缺少值。

    OOP仅允许OOP

    当你使用OOP时,尽可能多地使用它,一个对象是一个类的实例,声明了类,你知道它的内容是什么意思。如果不使用对象,则无法执行通用源。