C++ 我如何处理行为组合?
我正在考虑验证各种格式的实数的问题,因为这与我在设计中面临的问题非常相似 实数可以采用不同的格式组合,例如: 1.前面有/没有标志 2.带/不带小数点(如果没有小数点,则可以事先商定小数点的数量) 3.基数10或基数16 我们需要考虑每个组合,因此有2x2x2=8个组合。您可以看到,随着每个新条件的施加,复杂性呈指数级增加 在OO设计中,您通常会为每个数字格式分配一个类(例如,在本例中,我们有8个类),每个类都有一个单独的验证函数。然而,对于每一个新的条件,您必须将所需的类的数量增加一倍,这很快就会成为一场噩梦 在过程编程中,使用3个标志(即有符号、有小数点和数字基数)来标识要验证的实数的属性。您只有一个用于验证的函数。在那里,您将使用标志来控制其行为 } 同样,当函数被if语句和标志弄得乱七八糟时,复杂性很快就会失控 我相信您以前也遇到过这种性质的设计问题——许多导致行为差异的独立差异。我很想知道您是如何在不使代码完全无法维护的情况下实现解决方案的。C++ 我如何处理行为组合?,c++,oop,software-design,procedural-programming,C++,Oop,Software Design,Procedural Programming,我正在考虑验证各种格式的实数的问题,因为这与我在设计中面临的问题非常相似 实数可以采用不同的格式组合,例如: 1.前面有/没有标志 2.带/不带小数点(如果没有小数点,则可以事先商定小数点的数量) 3.基数10或基数16 我们需要考虑每个组合,因此有2x2x2=8个组合。您可以看到,随着每个新条件的施加,复杂性呈指数级增加 在OO设计中,您通常会为每个数字格式分配一个类(例如,在本例中,我们有8个类),每个类都有一个单独的验证函数。然而,对于每一个新的条件,您必须将所需的类的数量增加一倍,这很快
类似于桥接模式的东西会有所帮助吗?我不知道为什么您认为OO解决方案会为每个数字模式都包含一个类。我的OO解决方案是使用正则表达式类。如果我是程序性的,我可能会使用标准的library strod()函数。如果您需要解析器,请使用一个:
- sscanf
- boost::词法转换
- 还有很多其他的选择
设计模式和OOP很有用,但绝对不是解决每个问题的最佳方案。对不起,因为我使用vb,所以我所做的是一个基本函数,然后我结合了一个计算器函数 所以我会用我的方式来伪造代码 诸如此类,由你们来决定如何做二进制和八进制 在OO设计中,通常 为每个数字分配一个类 格式(例如,在本例中,我们有8个 类),每个类都有一个 单独的验证功能 没有。最多,您会有一个表示数字输入的类型(如果
String
没有);另一个是实数(在大多数语言中,您会选择内置类型,但无论如何);和一个解析器类,它具有获取数字输入并将其转换为实数的知识
更一般地说,行为的一个差异本身并不会自动映射到一个类。它可以只是类中的一个属性。最重要的是,行为应该正交处理
如果(想象你自己编写解析器)你可能有一个符号或者没有,一个小数点或者没有,十六进制或者没有,你有三个独立的复杂源,在某处找到三段代码,分别处理其中一个问题是可以的;但是,在任何地方都找不到2^3=8段不同的代码,它们以明确的方式处理不同的组合
想象一下,添加一个新选项:突然,您想起数字可能有一个“e”(如2.34e10),并希望能够支持它。使用正交策略,您将拥有另一个独立的复杂性来源,即第四个。用你的策略,8个案例会突然变成16个!显然是个禁忌。你不能用锤子打死苍蝇 我真的觉得用面向对象的解决方案来解决你的问题是一种极端的矫枉过正。仅仅因为你们可以设计面向对象的解决方案,并不意味着你们必须强迫这样的解决方案去解决你们的每一个问题 根据我的经验,几乎每次在找到一个问题的OOD解决方案时都会遇到困难,这可能意味着OOD并不合适。OOD只是一种工具,而不是上帝本身。它应该用来解决大规模的问题,而不是像你提出的那样的问题 所以给你一个实际的答案(如上面提到的):使用正则表达式,除此之外的所有解决方案都是多余的
如果你坚持使用OOD解决方案。。。。好的,因为你们展示的所有格式都是相互正交的,所以我认为并没有必要为每种可能的组合创建一个类。我会为每种格式创建一个类,并将我的输入传递给每种格式,在这种情况下,复杂性将线性增长。谢谢。那么,你是说你同意“程序性方法”(使用3个if…else语句来控制行为,假设它们不会相互交织)?我同意,随着独立的复杂性源数量的增加,使用类方法将很快成为一场噩梦。(1)在某一点上,有一个选择(对于每个不同的复杂性源)。当然,这个选择可以通过一个“如果”语句来完成;但是,是的,让他们保持独立。这并不是说“如果”是过程性的,而不是面向对象的——埃菲尔是最纯粹的面向对象语言之一,它有一个“如果”语句:)当然,其他选项是开关(类似于强大的“如果”),当选择对对象的身份至关重要时,通过继承实现多态性。此外,在某些情况下,模板(泛型)可能会
// This is part of the validation function
if (has_sign)
check_sign();
for (int i = 0; i < len; i++)
{
if (has_decimal_point)
// Check if number[i] is '.' and do something if it is. If not, continue
if (number_base = BASE10)
// number[i] must be between 0-9
else if (number_base = BASE16)
// number[i] must be between 0-9, A-F
function getrealnumber(number as int){ return getrealnumber(number.tostring) }
function getrealnumber(number as float){ return getrealnumber(number.tostring) }
function getrealnumber(number as double){ return getrealnumber(number.tostring) }
function getrealnumber(number as string){
if ishex(){ return evaluation()}
if issigned(){ return evaluation()}
if isdecimal(){ return evaluation()}
}