Setter是否应仅设置自身属性?API客户端请求修改方案咨询
关于Setter设计的核心原则与场景实践
这是个很务实的面向对象设计问题,咱们一步步拆解来看:
一、Setter的核心设计原则:守住单一职责
首先明确:Setter优先应该只负责设置自身的直接属性。这是单一职责原则的体现——一个类的方法只处理和自身强相关的逻辑,这样代码边界清晰、易测试、好维护。如果一个类的Setter跑去修改关联对象的属性,相当于把别人的职责揽过来了,时间久了类的职责会越来越模糊,出问题时很难定位根源。
二、你的API客户端场景:两种方案的利弊对比
回到你提到的场景:Client实例依赖XML配置,实例化后需要调整请求选项(XML里的$value),这里有两种常见方案,咱们具体分析:
方案1:用XML的Setter修改,再重新实例化Client
这种方案严格遵循单一职责:
- XML类负责自身属性的修改(比如写个
setRequestOption($key, $value)方法) - Client类只专注于基于XML配置发起API请求,不插手XML的修改逻辑
- 代码示例大概是这样:
优点是职责划分清晰,每个类只做自己的事;缺点是如果Client实例化成本很高(比如要建立持久连接、加载大量资源),频繁重新实例化会浪费性能。// 初始实例化流程 $xmlConfig = new XmlConfig($initialOptions); $client = new ApiClient($xmlConfig); // 需要调整配置时 $xmlConfig->setRequestOption('timeout', 30); $newClient = new ApiClient($xmlConfig); // 重新实例化Client
方案2:在Client里添加Setter直接修改XML属性
这种方案让Client承担了额外的职责:
- 在Client里加一个
setRequestOption($key, $value)方法,内部直接调用$this->xmlConfig->setRequestOption(...)甚至直接修改XML的属性 - 代码示例:
优点是不用重新实例化,性能更优;缺点是Client的职责变杂了——它不仅要处理API请求,还要管XML配置的修改,耦合度变高。如果以后XML配置的结构或规则变了,Client的代码也得跟着改,维护成本会越来越高。$client = new ApiClient($xmlConfig); $client->setRequestOption('timeout', 30); // 直接修改,无需重新实例化
三、折中方案:委托修改,兼顾性能与设计原则
如果既想避免重新实例化,又不想破坏单一职责,推荐用委托转发的方式:让Client提供修改配置的方法,但具体逻辑还是交给XML类处理,Client只做一层转发:
class ApiClient { private $xmlConfig; public function __construct(XmlConfig $xmlConfig) { $this->xmlConfig = $xmlConfig; } // 只做转发,不处理具体配置逻辑 public function updateRequestOption($key, $value) { $this->xmlConfig->setRequestOption($key, $value); } }
这种写法既满足了“不用重新实例化Client”的需求,又没有让Client越界承担XML的职责,算是兼顾了性能和设计原则的最优解。
四、最终选择建议
- 如果Client实例化成本很低:优先选方案1,保持职责清晰最简单
- 如果Client实例化成本高,且需要频繁修改配置:选上面的折中方案,委托转发
- 绝对要避免的写法:让Client直接操作XML的内部属性(比如
$this->xmlConfig->value = xxx),这种强耦合的代码后期维护会非常头疼
内容的提问来源于stack exchange,提问作者laketuna
相关产品推荐
相关产品推荐

