代码之家  ›  专栏  ›  技术社区  ›  raoulsson

将布尔值包装在对象中

  •  4
  • raoulsson  · 技术社区  · 15 年前

    我有一些代码要重构。我有很多方法采用相同类型的多个参数,例如:

    public void foo(String name, String street, boolean b1, boolean b2) { ... }
    

    等等。因为不同的对象只能通过名称来区分,所以我想将它们包装在对象(枚举)中,以便 字体系统的使用 语言(Java在这种情况下)。

    public class Name {
        private String value;
        public String getValue() { return value; }
        // ...
    }
    

    像这样,我可以强制调用代码传入特定类型的对象。这样可以确保它不会意外地混淆方法参数的顺序,从而 运行时不产生意外行为 :

    foo(new Name("John"), new Street("Broadway"), new B1(true), new B2(false);
    

    这使得 重构更安全 ,您可以在系统中携带对象,只要您想要,其中的数据,字符串在任何时候都是安全的。 只有在你需要的时候 ,通过调用getValue()获得它。

    现在,对于包装字符串的对象,它非常简单,因为有很多状态实例可以存在。

    但是布尔包装器呢? 这些要么是对的,要么是错的。这个实现看起来有点滑稽:

    public enum Quanto {
    
        YES() {
            protected boolean isQuanto() {
                return true;
            }
        },
        NO() {
            protected boolean isQuanto() {
                return false;
            }
        };
    
        protected abstract boolean isQuanto();
    
    }
    

    更奇怪的是,我发现调用代码是什么样子的:

    public void doStuff(Quanto quanto) {
        if(quanto.isQuanto()) {
            // ...
        }
    }
    

    从技术上讲,这当然不重要,但只是感觉不对劲…你有没有找到更好的处理方法?

    编辑: 我也不高兴的是,有更多的价值观比 在上面的例子中,假设 也许吧 ……?!

    谢谢!

    4 回复  |  直到 15 年前
        1
  •  9
  •   ChssPly76    15 年前

    我将把布尔值包装成语义枚举。换言之:

    public void doStuff(boolean isActive, boolean wrapResult);
    

    变成

    public enum State {ACTIVE, INACTIVE};
    public enum ResultMode {WRAPPED, UNWRAPPED};
    
    public void doStuff(State state, ResultMode resultsMode);
    
        2
  •  4
  •   me22    15 年前

    基本上,您要做的是命名参数,所以我建议每个函数一个类,每个参数都有成员。

    然后,呼叫站点看起来会像这样:

    foo(new foo_arguments().Name("John").Street("Broadway").B1(true).B2(false));
    

    然后在函数内部使用arguments.name()等。

    这样做的另一个好处是,您可以在不进行大量重载的情况下提供默认参数,并且可以按任意顺序指定参数,因此这是可行的:

    foo(new foo_arguments().Street("Sesame").Name("Monster"));
    

    所需课程:

    public class foo_arguments {
        private string _name = "John Doe";
        public foo_arguments Name(string name) { _name = name; return this; }
        public string Name() { return _name; }
    
        private string _street = "Pennsylvania Ave NW";
        public foo_arguments Street(string street) { _street = street; return this; }
        public string Street() { return _street; }
    
        private string _b1 = false;
        public foo_arguments B1(string b1) { _b1 = b1; return this; }
        public boolean B1() { return _b1; }
    
        private string _b2 = true;
        public foo_arguments B2(string b2) { _b2 = b2; return this; }
        public boolean B2() { return _b2; }
    }
    

    顺便说一句,在C中,您可以用自动属性和对象初始值设定项非常优雅地完成这项工作。

        3
  •  2
  •   Janusz Daniel Rindt    15 年前

    方法是否总是采用相同的参数集?如果是这样,您可能希望创建一个存储所有数据的数据对象,并且只向函数提供该对象。也许您甚至可以稍后将函数移动到对象中。 有时将方法与许多输入参数放在一起意味着缺少所有这些参数的对象。

    我不会费心在一个对象中封装一个布尔值。我觉得不太合适。

        4
  •  1
  •   aperkins    15 年前

    为什么不为传入方法的不同值提供封装对象,而不是为布尔值提供枚举呢?这样,值就位于getter和setter上,并具有所需的信息:

    public class Encapsulator {
    
        private boolean isSelected;
        private boolean isAwake;
    
    
        public boolean isAwake() {
            return isAwake;
        }
    
        public void setIsAwake(boolean isAwake) {
            this.isAwake = isAwake;
        }
    
        public boolean isSelected() {
            return isSelected;
        }
    
        public void setIsSelected(boolean isSelected) {
            this.isSelected = isSelected;
        }
    }
    

    这样,当您访问数据时,很明显对象中的一个特定元素会做一件或另一件事情。它还减少了方法的参数集,根据MartinFowler的说法,这是一种代码味道。