面向对象软件设计处理约束 - 使用哪种设计模式?
OO Software desing handling constraints - which design pattern to use?
我有一个关于软件设计的问题。我认为我正在寻找的是一个众所周知的问题,因此必须有一种设计模式或多种模式来解决它。但是我想不通。
好的,问题来了。例如,假设我有以下 类 和属性:
C任务
- 姓名
- 持续时间
- 任务区域
CTaskArea
- 姓名
个人
- 姓名
- 能力
能力
- 姓名
C工具
- 姓名
- 清洁时间
C约束
- 姓名
- 约束
CTask、CPerson、CTool 可能有约束,例如任务 A 只能由具有 X 能力的人完成,或者 A 不能完成 TaskArea X 的任务等等。例如,当我创建一个新的 CTask、CPerson 或 CTool 时,我可以想象一个带有 dropdwons 的约束配置对话框:
Class |接线员 | Class | 属性 |值
C 人 |不 | C工具|名称 |锤子
最好的设计方法是什么,以便有机会为所有可能具有约束的 类 动态配置约束?我开始研究观察者模式以注册所有支持 类 的联合约束,但我认为有更好的方法。你怎么看?
编辑:
更准确地说。我想避免的是 CPerson 或 CTool 等包含彼此的信息。
我想到了类似约束接口的东西,它必须由 类 实现,它可能有约束。然后,在运行时,我寻找已实现该接口的实例并将它们放入列表中以进行进一步的操作,例如定义约束等。
当我第一次想到如何实现它时,我想知道是否已经有一个现有的设计模式,因为它似乎是一个普遍的问题。不幸的是,我找不到真正适合问题的方法。有什么想法吗?
提前致谢!
蒂姆
编辑:我目前正在研究基于继承的解决方案,我将在它工作时post这里:)
为什么不在每个具有特定 xxx
属性 约束的对象处设置 contraints_for_xxx
属性?
当某个子属性要加入一个集合时,首先运行通过constraints集合。如果任何约束项returns false...抛出异常,天上打雷等
可以在对象的构造函数中或稍后通过一些 setupConstraints()
调用来填充约束。
CPerson 可以看起来像(PHP 示例):
class Person
{
protected $constraintsAbc = null;
public function setConstraintsAbc(array $constraints)
{
$this->constraintsAbc = $constraints;
}
public function setABC($value)
{
foreach ($this->constraintsAbc as $constraint) {
if (!$constraint->isValid($value)) {
throw new Exception("Constraint {$constraint->getName()} is not happy with value $value");
}
}
$this->abc = $value;
}
}
class PersonSetup
{
public function setupPerson(Person $person)
{
$constrains[] = new PersonAbcConstraint("Value > 5");
$person->setContraintsABC($constrains);
}
}
这当然是虚构的例子。在某些代码重复中存在问题,因为您将 constraintsAbc
、setConstraintsAbc
和 setAbc
作为不同的硬编码字段。但是如果你愿意,你可以将它抽象成一些虚拟的 "constraintable" 字段集合。
这是我可以接受的解决方案:
class CCouldHaveConstraints_Base
{
public virtual GetInstance();
public virtual GetClassName();
public virtual GetPropertyListThatCouldHaveConstraints();
}
class CPerson : CCouldHaveConstraints_Base
{
private String m_PersonName;
private String m_PersonAge;
public String PersonName
{
get {return this.m_PersonName;}
set {this.m_PersonName=value;}
}
public String PersonAge
{
get {return this.m_PersonAge;}
set {this.m_PersonAge=value;}
}
public override GetInstance()
{
return new CPerson;
}
public override GetClassName
{
return "Person";
}
public list<string> GetPropertyListThatCouldHaveConstraints()
{
list <string> ConstraintPropsList = new list<string>;
ConstraintPropsList.Add ("PersonName")
}
}
// class contains a list of all objects that could have constraints
class CConstraint_Lst
{
private list<CConstraint> m_ListOfConstraints;
private list<CCouldHaveConstraints_Base> m_ListOfObjectsThatCouldHaveConstraints;
}
// e.g Person | Person.Name | Tim | NOT | Tool | Tool.Name | "Hammer"
class CConstraint
{
private String m_ClassName_A;
private String m_ClassProperty_A;
private String m_ClassProperty_A_Value;
private String m_Operator;
private String m_ClassName_B;
private String m_ClassProperty_B;
private String m_ClassProperty_B_Value;
}
这些代码是否足以弄清楚我的想法?
此致,
蒂姆
我有一个关于软件设计的问题。我认为我正在寻找的是一个众所周知的问题,因此必须有一种设计模式或多种模式来解决它。但是我想不通。
好的,问题来了。例如,假设我有以下 类 和属性:
C任务
- 姓名
- 持续时间
- 任务区域
CTaskArea
- 姓名
个人
- 姓名
- 能力
能力
- 姓名
C工具
- 姓名
- 清洁时间
C约束
- 姓名
- 约束
CTask、CPerson、CTool 可能有约束,例如任务 A 只能由具有 X 能力的人完成,或者 A 不能完成 TaskArea X 的任务等等。例如,当我创建一个新的 CTask、CPerson 或 CTool 时,我可以想象一个带有 dropdwons 的约束配置对话框:
Class |接线员 | Class | 属性 |值
C 人 |不 | C工具|名称 |锤子
最好的设计方法是什么,以便有机会为所有可能具有约束的 类 动态配置约束?我开始研究观察者模式以注册所有支持 类 的联合约束,但我认为有更好的方法。你怎么看?
编辑: 更准确地说。我想避免的是 CPerson 或 CTool 等包含彼此的信息。 我想到了类似约束接口的东西,它必须由 类 实现,它可能有约束。然后,在运行时,我寻找已实现该接口的实例并将它们放入列表中以进行进一步的操作,例如定义约束等。 当我第一次想到如何实现它时,我想知道是否已经有一个现有的设计模式,因为它似乎是一个普遍的问题。不幸的是,我找不到真正适合问题的方法。有什么想法吗?
提前致谢!
蒂姆
编辑:我目前正在研究基于继承的解决方案,我将在它工作时post这里:)
为什么不在每个具有特定 xxx
属性 约束的对象处设置 contraints_for_xxx
属性?
当某个子属性要加入一个集合时,首先运行通过constraints集合。如果任何约束项returns false...抛出异常,天上打雷等
可以在对象的构造函数中或稍后通过一些 setupConstraints()
调用来填充约束。
CPerson 可以看起来像(PHP 示例):
class Person
{
protected $constraintsAbc = null;
public function setConstraintsAbc(array $constraints)
{
$this->constraintsAbc = $constraints;
}
public function setABC($value)
{
foreach ($this->constraintsAbc as $constraint) {
if (!$constraint->isValid($value)) {
throw new Exception("Constraint {$constraint->getName()} is not happy with value $value");
}
}
$this->abc = $value;
}
}
class PersonSetup
{
public function setupPerson(Person $person)
{
$constrains[] = new PersonAbcConstraint("Value > 5");
$person->setContraintsABC($constrains);
}
}
这当然是虚构的例子。在某些代码重复中存在问题,因为您将 constraintsAbc
、setConstraintsAbc
和 setAbc
作为不同的硬编码字段。但是如果你愿意,你可以将它抽象成一些虚拟的 "constraintable" 字段集合。
这是我可以接受的解决方案:
class CCouldHaveConstraints_Base
{
public virtual GetInstance();
public virtual GetClassName();
public virtual GetPropertyListThatCouldHaveConstraints();
}
class CPerson : CCouldHaveConstraints_Base
{
private String m_PersonName;
private String m_PersonAge;
public String PersonName
{
get {return this.m_PersonName;}
set {this.m_PersonName=value;}
}
public String PersonAge
{
get {return this.m_PersonAge;}
set {this.m_PersonAge=value;}
}
public override GetInstance()
{
return new CPerson;
}
public override GetClassName
{
return "Person";
}
public list<string> GetPropertyListThatCouldHaveConstraints()
{
list <string> ConstraintPropsList = new list<string>;
ConstraintPropsList.Add ("PersonName")
}
}
// class contains a list of all objects that could have constraints
class CConstraint_Lst
{
private list<CConstraint> m_ListOfConstraints;
private list<CCouldHaveConstraints_Base> m_ListOfObjectsThatCouldHaveConstraints;
}
// e.g Person | Person.Name | Tim | NOT | Tool | Tool.Name | "Hammer"
class CConstraint
{
private String m_ClassName_A;
private String m_ClassProperty_A;
private String m_ClassProperty_A_Value;
private String m_Operator;
private String m_ClassName_B;
private String m_ClassProperty_B;
private String m_ClassProperty_B_Value;
}
这些代码是否足以弄清楚我的想法?
此致, 蒂姆