装饰者模式适合这里吗
Is decorator pattern suitable here
所以我有几个 classes,A
,B
,C
,... N
。还有一些可能的属性,setP()
、setQ()
、setR()
、... setZ()
。现在,每个 class 可以有不同的属性组合:
A B C N
- setX - setR - setP - setY
- setY - setZ - setQ - setZ
- setZ - setR
- setS
- setZ
所有 setters return 对象本身的实例,以便可以进行链接。
我正在尝试找到一种优雅的方法来解决这个问题。我不想重新定义每个 class 中的数十个属性(代码重复),我也不想使用继承,因为会有丑陋、毫无意义的中间 classes (BaseABCD -> setZ
) 和 cuz基础 class setter 将 return 类型 BaseABCD
的实例,这将不允许所有属性的完整链接。
以下是我正在尝试研究的一些可能的事情:
以某种方式将每个 属性 定义为优雅时尚的装饰器,并组成 A
类似于 Base.decorators().addX().addY().addZ().finalize()
.
在 Base
中定义所有可能的属性,并在派生的 class 中隐藏不需要的属性。我认为这是不可能的。
这些事情有可能吗?或者有更好的办法来解决这样的问题吗?
更多详情
classes 基本上是应用程序用来与外部系统通信的不同消息类型。不同的消息包含不同类型的不同字段。例如:
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>
。每个 属性 对应于 class 的哈希图中的一个键。序列化时,我只是遍历 class 哈希图中的所有 key/value 条目并生成要发送的字符串消息表示形式。
但是,我想对调用者代码强制执行类型。所以我不想公开像 A.set('RESOURCEIDENTIFIER', '123456')
这样的方法。相反,我想公开 A.setResourceIdentifier(123456)
和 C.setOperation(OperationType.DELETE)
.
等方法
在内部,这些 setter 函数只是将相关键放入哈希图中并为其分配一个字符串值。
public A setOperation(OperationType operation) {
this.hashmap.put('OPERATION', operation.name());
return this;
}
大约有 40 种独特的字段类型,所有消息都使用这些字段的独特子集。像 A
和 B
包含 setTimestamp()
。 B
和 C
包含 setResourceIdentifier()
。只有 C
包含 setOperationType()
。等等。
我不想一遍又一遍地在每个class中重新定义这几十个属性。这就是为什么我想探索以下两个选项:
选项 1
定义具有所有可能属性的 Base
class,并在派生的 A
class 中,仅将必需的属性覆盖为 public。这是可行的。但我想看看是否有可能实现选项 #2 中描述的内容。
选项 2
以某种方式定义装饰器和工厂 class 这样
public ? getA() {
return Base.startDecorating()
.addTimestamp()
.addResourceIdentifier()
.finalize();
}
? objA = Factory.getA()
.setTimestamp(DateTime.now())
.setResourceIdentifier(123456);
这可能吗?在写出这个问题时,我意识到选项 1 应该是可行的方法。它简单且不易出错。但出于好奇,我想知道装饰器模式是否可以在这里使用。毕竟,我这里有一套完整的独立模块(属性)和将它们组装在一起的不同方式(classes)。
根据属性的名称,我猜您是在尝试定义不同的坐标表示法?为什么不使用具有所有属性的一个基数 class?
这些实际上并没有那么多属性,您不能将它们组合成随机排列。那么,为什么要把每件事都变得比必要的更复杂呢?
我认为 Decorator 不适合这里:装饰器的意义在于保持透明。如果您这样定义您的属性,则必须检查(属性 的类型或是否存在)每次访问。
如果属性的 setter 中有一些在多个主要 class 中共享的逻辑,装饰器模式可以适合并且是一种很好的设计方法。如果不是,例如你确定他们所做的只是 this.x=x
或者每个 class 设置一个 属性 某种类型的不同然后没有。
您可以为每个属性定义一个 class,并让您的主要 classes 具有属性类型 classes 的变量。这样,当在主 class 上设置 属性 时,它会将工作委托给适当的 属性 class 的 setter,这样您就可以定义setter 一次使用,随处使用。同样,如果您在 setter 中有更多逻辑然后 this.x=x;
,这可能是最好的主意。
哦,在将设置的作业委托给 属性 class 之后,您仍然可以 return this
进行链接。
此外,如果您懒惰并且不太关心实时性能,您可以使用反射来简化主要 classes 的编码。
装饰器是为您可以不断添加的东西而设计的。就像一棵圣诞树。但是一旦圣诞树装饰好了,那么你就可以使用turnOn()
这样的常用方法。它不是为向现有 API 添加新方法而制作的。我认为您可以为此使用常规的旧继承。我也会使用像 List 这样的例子。你的Baseclass可以提供大家共享的常用方法,然后互相子class添加新的方法。
为了帮助保持清洁,您可以添加工厂或生成器来简化操作。
这里有一些例子。假设基数class被称为Base
,sub-classes是一个名为classes、A
、B
等的字母
工厂示例1.
Base x = factory.getInstance(A.class);
工厂示例2.
Map props = ...;
Base x = factory.getInstance(A.class, props);
生成器示例 1.
Base x = new ABuilder().setX(x).setY(y).setZ(z).create();
这涉及为每个单独的子 class 创建构建器 class。子 class 构建器 classes 可能继承也可能不继承抽象 BaseBuilder
class,后者定义了带有签名 public Base create();
.
的方法
所以我有几个 classes,A
,B
,C
,... N
。还有一些可能的属性,setP()
、setQ()
、setR()
、... setZ()
。现在,每个 class 可以有不同的属性组合:
A B C N
- setX - setR - setP - setY
- setY - setZ - setQ - setZ
- setZ - setR
- setS
- setZ
所有 setters return 对象本身的实例,以便可以进行链接。
我正在尝试找到一种优雅的方法来解决这个问题。我不想重新定义每个 class 中的数十个属性(代码重复),我也不想使用继承,因为会有丑陋、毫无意义的中间 classes (BaseABCD -> setZ
) 和 cuz基础 class setter 将 return 类型 BaseABCD
的实例,这将不允许所有属性的完整链接。
以下是我正在尝试研究的一些可能的事情:
以某种方式将每个 属性 定义为优雅时尚的装饰器,并组成
A
类似于Base.decorators().addX().addY().addZ().finalize()
.在
Base
中定义所有可能的属性,并在派生的 class 中隐藏不需要的属性。我认为这是不可能的。
这些事情有可能吗?或者有更好的办法来解决这样的问题吗?
更多详情
classes 基本上是应用程序用来与外部系统通信的不同消息类型。不同的消息包含不同类型的不同字段。例如:
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>
。每个 属性 对应于 class 的哈希图中的一个键。序列化时,我只是遍历 class 哈希图中的所有 key/value 条目并生成要发送的字符串消息表示形式。
但是,我想对调用者代码强制执行类型。所以我不想公开像 A.set('RESOURCEIDENTIFIER', '123456')
这样的方法。相反,我想公开 A.setResourceIdentifier(123456)
和 C.setOperation(OperationType.DELETE)
.
在内部,这些 setter 函数只是将相关键放入哈希图中并为其分配一个字符串值。
public A setOperation(OperationType operation) {
this.hashmap.put('OPERATION', operation.name());
return this;
}
大约有 40 种独特的字段类型,所有消息都使用这些字段的独特子集。像 A
和 B
包含 setTimestamp()
。 B
和 C
包含 setResourceIdentifier()
。只有 C
包含 setOperationType()
。等等。
我不想一遍又一遍地在每个class中重新定义这几十个属性。这就是为什么我想探索以下两个选项:
选项 1
定义具有所有可能属性的 Base
class,并在派生的 A
class 中,仅将必需的属性覆盖为 public。这是可行的。但我想看看是否有可能实现选项 #2 中描述的内容。
选项 2 以某种方式定义装饰器和工厂 class 这样
public ? getA() {
return Base.startDecorating()
.addTimestamp()
.addResourceIdentifier()
.finalize();
}
? objA = Factory.getA()
.setTimestamp(DateTime.now())
.setResourceIdentifier(123456);
这可能吗?在写出这个问题时,我意识到选项 1 应该是可行的方法。它简单且不易出错。但出于好奇,我想知道装饰器模式是否可以在这里使用。毕竟,我这里有一套完整的独立模块(属性)和将它们组装在一起的不同方式(classes)。
根据属性的名称,我猜您是在尝试定义不同的坐标表示法?为什么不使用具有所有属性的一个基数 class?
这些实际上并没有那么多属性,您不能将它们组合成随机排列。那么,为什么要把每件事都变得比必要的更复杂呢?
我认为 Decorator 不适合这里:装饰器的意义在于保持透明。如果您这样定义您的属性,则必须检查(属性 的类型或是否存在)每次访问。
如果属性的 setter 中有一些在多个主要 class 中共享的逻辑,装饰器模式可以适合并且是一种很好的设计方法。如果不是,例如你确定他们所做的只是 this.x=x
或者每个 class 设置一个 属性 某种类型的不同然后没有。
您可以为每个属性定义一个 class,并让您的主要 classes 具有属性类型 classes 的变量。这样,当在主 class 上设置 属性 时,它会将工作委托给适当的 属性 class 的 setter,这样您就可以定义setter 一次使用,随处使用。同样,如果您在 setter 中有更多逻辑然后 this.x=x;
,这可能是最好的主意。
哦,在将设置的作业委托给 属性 class 之后,您仍然可以 return this
进行链接。
此外,如果您懒惰并且不太关心实时性能,您可以使用反射来简化主要 classes 的编码。
装饰器是为您可以不断添加的东西而设计的。就像一棵圣诞树。但是一旦圣诞树装饰好了,那么你就可以使用turnOn()
这样的常用方法。它不是为向现有 API 添加新方法而制作的。我认为您可以为此使用常规的旧继承。我也会使用像 List 这样的例子。你的Baseclass可以提供大家共享的常用方法,然后互相子class添加新的方法。
为了帮助保持清洁,您可以添加工厂或生成器来简化操作。
这里有一些例子。假设基数class被称为Base
,sub-classes是一个名为classes、A
、B
等的字母
工厂示例1.
Base x = factory.getInstance(A.class);
工厂示例2.
Map props = ...; Base x = factory.getInstance(A.class, props);
生成器示例 1.
Base x = new ABuilder().setX(x).setY(y).setZ(z).create();
这涉及为每个单独的子 class 创建构建器 class。子 class 构建器 classes 可能继承也可能不继承抽象 BaseBuilder
class,后者定义了带有签名 public Base create();
.