【发布时间】:2016-09-04 06:51:09
【问题描述】:
所以我有几节课,A、B、C、...N。还有几个可能的属性,setP()、setQ()、setR()、...setZ()。现在,每个类都可以有不同的属性组合:
A B C N
- setX - setR - setP - setY
- setY - setZ - setQ - setZ
- setZ - setR
- setS
- setZ
所有的setter都返回对象本身的一个实例,这样就可以进行链接了。
我试图找到一种优雅的方法来解决这个问题。我不想重新定义每个类中的数十个属性(代码重复),我不想使用继承,因为会有丑陋、毫无意义的中间类(BaseABCD -> setZ)并且因为基类设置器将返回@类型的实例987654331@ 这将不允许所有属性的完整链接。
这里有一些我试图调查的可能的事情:
以某种方式以优雅的方式将每个属性定义为装饰器,并编写
A类似Base.decorators().addX().addY().addZ().finalize()的东西。在
Base中定义所有可能的属性,并在派生类中隐藏不需要的属性。我认为这是不可能的。
这些事情有可能吗?还是有更好的办法来解决这样的问题?
更多详情
这些类基本上是应用程序用来与外部系统通信的不同消息类型。不同的消息包含不同类型的不同字段。例如:
ECHO message:
- Timestamp (DateTime)
- SourceAddress (String)
CHECK RESOURCE message:
- Timestamp (DateTime)
- Resource Identifier (Integer)
MANIPULATE RESOURCE
- Resource Identifier (Integer)
- Operation Type (Enum)
消息在传输时被序列化为字符串,并且不保留类型信息。所以我选择了HashMap<String, String>。每个属性对应于该类的哈希图中的一个键。序列化时,我只是遍历该类的 hashmap 中的所有键/值条目并生成要发送的字符串消息表示。
但是,我想对调用者代码强制执行类型。所以我不想暴露像A.set('RESOURCEIDENTIFIER', '123456') 这样的方法。相反,我想公开像 A.setResourceIdentifier(123456) 和 C.setOperation(OperationType.DELETE) 这样的方法。
在内部,这些 setter 函数只是将一个相关的键放入 hashmap 并为其分配一个字符串值。
public A setOperation(OperationType operation) {
this.hashmap.put('OPERATION', operation.name());
return this;
}
大约有 40 种独特的字段类型,所有消息都使用这些字段的独特子集。比如A 和B 包含setTimestamp()。 B 和 C 包含 setResourceIdentifier()。只有C 包含setOperationType()。以此类推。
我不想一遍又一遍地重新定义每个类中的这几十个属性。这就是为什么我想探索以下两个选项:
选项 1
定义具有所有可能属性的Base 类,并在派生的A 类中,仅覆盖所需的公共属性。这是可行的。但我想看看是否有可能实现选项 #2 中描述的内容。
选项 2 以某种方式定义装饰器和工厂类,以便
public ? getA() {
return Base.startDecorating()
.addTimestamp()
.addResourceIdentifier()
.finalize();
}
? objA = Factory.getA()
.setTimestamp(DateTime.now())
.setResourceIdentifier(123456);
这可能吗?在写出这个问题时,我意识到选项 1 应该是要走的路。它简单且不易出错。但出于好奇,我想知道是否可以在这里使用装饰器模式。毕竟,我这里拥有的是一套完整的独立模块(属性)以及将它们组合在一起的不同方式(类)。
【问题讨论】:
-
在这种情况下继承有什么难看的?你能提供更具体的例子吗? setX Y Z 没有帮助。
-
创建这些对象的类或方法是否与基类或子类交互?以 List 为例,它是否知道它使用的是 LinkedList 而不是一个 List?
-
用一个基础枚举集来保存属性的基类怎么样?
-
@Pacente。这当然是当前的实现,但我想看看我是否可以成功地将装饰器模式应用于这个问题。但看起来很难实现。