序列化复合材料的最佳方式 - (设计模式)
Best way to serialize composite - (design pattern)
我有以下 java 复合设计模式实现代码:
//composite designed for type safety (all Leaf-only operations only in leaf)
interface Component extends Visitable {
void enable();
void disable();
}
class CompositeA implements Component {
private String compositeData;
private boolean enabled;
private Set<Component> components = new HashSet<>();
CompositeA(String compositeData) {
this.compositeData = compositeData;
}
void addChild(Component component){
this.components.add(component);
}
String getCompositeData() {
return compositeData;
}
Set<Component> getComponents() {
return components;
}
@Override
public void enable() {
this.enabled = true;
}
@Override
public void disable() {
this.enabled = false;
}
@Override
public Object accept(ComponentVisitor visitor) {
return visitor.visit(this);
}
}
class CompositeB implements Component{
private int compositeData;
private boolean enabled;
private Set<Component> components = new HashSet<>();
CompositeB(int compositeData) {
this.compositeData = compositeData;
}
void addChild(Component component){
this.components.add(component);
}
int getCompositeData() {
return compositeData;
}
Set<Component> getComponents() {
return components;
}
@Override
public void enable() {
this.enabled = true;
}
@Override
public void disable() {
this.enabled = false;
}
@Override
public Object accept(ComponentVisitor visitor) {
return visitor.visit(this);
}
}
class Leaf implements Component {
private boolean enabled;
private String[] leafData;
Leaf(String[] leafData) {
this.leafData = leafData;
}
String[] getLeafData() {
return leafData;
}
@Override
public void enable() {
this.enabled = true;
}
@Override
public void disable() {
this.enabled = false;
}
@Override
public Object accept(ComponentVisitor visitor) {
return visitor.visit(this);
}
}
这里有2个可能的复合根(CompositeA
和CompositeB
)和一个叶子组件(Leaf
)。
这里我定义了将保存序列化数据的 DTO:
class WholeCompositeASerialized {
String content;
List<Object> serializedChildren;
}
class WholeCompositeBSerialized{
String content;
List<Object> serializedChildren;
}
class WholeLeafSerialized{
String content;
}
现在如果我使用访问者模式进行序列化,我会得到这样的结果:
interface ComponentVisitor {
WholeCompositeASerialized visit(CompositeA compositeA);
WholeCompositeBSerialized visit(CompositeB compositeB);
WholeLeafSerialized visit(Leaf leaf);
}
class SerializableComponentVisitor implements ComponentVisitor{
@Override
public WholeCompositeASerialized visit(CompositeA compositeA) {
WholeCompositeASerialized wcas = new WholeCompositeASerialized();
wcas.serializedChildren = compositeA
.getComponents()
.stream()
.map(c -> c.accept(this))
.collect(Collectors.toList());
wcas.content = compositeA.getCompositeData();
return wcas;
}
@Override
public WholeCompositeBSerialized visit(CompositeB compositeB) {
WholeCompositeBSerialized wcbs = new WholeCompositeBSerialized();
wcbs.serializedChildren = compositeB
.getComponents()
.stream()
.map(c -> c.accept(this))
.collect(Collectors.toList());
wcbs.content = String.valueOf(compositeB.getCompositeData());
return wcbs;
}
@Override
public WholeLeafSerialized visit(Leaf leaf) {
WholeLeafSerialized wls = new WholeLeafSerialized();
wls.content = Arrays.toString(leaf.getLeafData());
return wls;
}
}
interface Visitable{
Object accept(ComponentVisitor visitor);
}
如果我使用 instanceof
这是执行相同操作的代码:
class SerializerUsingInstanceOf {
Object decide(Component component){
if(component instanceof CompositeA){
return serialize((CompositeA)component);
}
else if(component instanceof CompositeB){
return serialize((CompositeB)component);
}
else{
return serialize((Leaf)component);
}
}
WholeCompositeASerialized serialize(CompositeA compositeA) {
WholeCompositeASerialized wcas = new WholeCompositeASerialized();
wcas.serializedChildren = compositeA
.getComponents()
.stream()
.map(this::decide)
.collect(Collectors.toList());
wcas.content = compositeA.getCompositeData();
return wcas;
}
WholeCompositeBSerialized serialize(CompositeB compositeB) {
WholeCompositeBSerialized wcbs = new WholeCompositeBSerialized();
wcbs.serializedChildren = compositeB
.getComponents()
.stream()
.map(this::decide)
.collect(Collectors.toList());
wcbs.content = String.valueOf(compositeB.getCompositeData());
return wcbs;
}
WholeLeafSerialized serialize(Leaf leaf) {
WholeLeafSerialized wls = new WholeLeafSerialized();
wls.content = Arrays.toString(leaf.getLeafData());
return wls;
}
}
我猜这里首选访问者,因为当我们添加新的 Component
时,我们还需要实现 Object accept(ComponentVisitor visitor)
方法 - 所以我们不能忘记我们需要一个代码来序列化这个新组件。如果我们在使用 instanceof
时也这样做,我们可能会忘记将其添加到该检查中。
现在 - 我的问题是 - 有什么方法可以摆脱丑陋的 Object
return 输入 Object accept(ComponentVisitor visitor)
方法签名?我想到的唯一其他选择是使用一些标记接口(例如 interface SerializedComponent {}
),然后让所有序列化程序 类 像这样 class WholeCompositeASerialized implements SerializedComponent
实现该空接口,但它仍然没有似乎是对的。
我认为正确的方法是在这里使用泛型。
例如https://onlinegdb.com/r1m5Eg4DP
public class Main {
public static void main(String []args){
ComponentVisitor<SerializedComponent> serializer = new ComponentSerializer();
Component componentA = new ComponentA();
SerializedComponent serializedA = componentA.accept(serializer);
System.out.println(serializedA);
Component component = new ComponentB();
SerializedComponent serializedB = component.accept(serializer);
System.out.println(serializedB);
}
static interface Component {
public <V> V accept(ComponentVisitor<V> visitor);
}
static class ComponentA implements Component {
public <V> V accept(ComponentVisitor<V> visitor) {
return visitor.visit(this);
}
}
static class ComponentB implements Component {
public <V> V accept(ComponentVisitor<V> visitor) {
return visitor.visit(this);
}
}
static interface SerializedComponent {}
static class SerializedComponentA implements SerializedComponent {
}
static class SerializedComponentB implements SerializedComponent {
}
static interface ComponentVisitor<V> {
public V visit(ComponentA component);
public V visit(ComponentB component);
}
static class ComponentSerializer implements ComponentVisitor<SerializedComponent> {
public SerializedComponent visit(ComponentA component) {
return new SerializedComponentA();
}
public SerializedComponent visit(ComponentB component) {
return new SerializedComponentB();
}
}
}
您正在尝试 return 来自访问者的具体类型信息。这不是该模式的目的。访问者在内部封装(和处理)具体类型。
这里的解决方案是将 all 特定于 ComponentA
的逻辑(或您可能将其转换为的任何 A-specific 类型)移动到 visit(ComponentA)
方法,同样适用于 ComponentB
.
如果不想要Visitor的类型封装,那么另一种设计更合适,比如模式匹配。
评论评论...
public static void main(String[] args) {
// Using a concrete type here defeats the purpose of these patterns.
// Instead, program to an interface:
// Component c1 = new CompositeA("root");
CompositeA c1 = new CompositeA("root");
c1.addChild(new Leaf(new String[]{"leaf11", "leaf12"}));
CompositeA c2 = new CompositeA("composite1");
c2.addChild(new Leaf(new String[]{"leaf21", "leaf22"}));
c1.addChild(c2);
SerializableComponentVisitor scv = new SerializableComponentVisitor();
// Clients never invoke visit methods directly,
// because they do not have the type information to make these calls.
// A client would execute, c1.accept(scv)
WholeCompositeASerialized wcas1 = scv.visit(c1);
}
我有以下 java 复合设计模式实现代码:
//composite designed for type safety (all Leaf-only operations only in leaf)
interface Component extends Visitable {
void enable();
void disable();
}
class CompositeA implements Component {
private String compositeData;
private boolean enabled;
private Set<Component> components = new HashSet<>();
CompositeA(String compositeData) {
this.compositeData = compositeData;
}
void addChild(Component component){
this.components.add(component);
}
String getCompositeData() {
return compositeData;
}
Set<Component> getComponents() {
return components;
}
@Override
public void enable() {
this.enabled = true;
}
@Override
public void disable() {
this.enabled = false;
}
@Override
public Object accept(ComponentVisitor visitor) {
return visitor.visit(this);
}
}
class CompositeB implements Component{
private int compositeData;
private boolean enabled;
private Set<Component> components = new HashSet<>();
CompositeB(int compositeData) {
this.compositeData = compositeData;
}
void addChild(Component component){
this.components.add(component);
}
int getCompositeData() {
return compositeData;
}
Set<Component> getComponents() {
return components;
}
@Override
public void enable() {
this.enabled = true;
}
@Override
public void disable() {
this.enabled = false;
}
@Override
public Object accept(ComponentVisitor visitor) {
return visitor.visit(this);
}
}
class Leaf implements Component {
private boolean enabled;
private String[] leafData;
Leaf(String[] leafData) {
this.leafData = leafData;
}
String[] getLeafData() {
return leafData;
}
@Override
public void enable() {
this.enabled = true;
}
@Override
public void disable() {
this.enabled = false;
}
@Override
public Object accept(ComponentVisitor visitor) {
return visitor.visit(this);
}
}
这里有2个可能的复合根(CompositeA
和CompositeB
)和一个叶子组件(Leaf
)。
这里我定义了将保存序列化数据的 DTO:
class WholeCompositeASerialized {
String content;
List<Object> serializedChildren;
}
class WholeCompositeBSerialized{
String content;
List<Object> serializedChildren;
}
class WholeLeafSerialized{
String content;
}
现在如果我使用访问者模式进行序列化,我会得到这样的结果:
interface ComponentVisitor {
WholeCompositeASerialized visit(CompositeA compositeA);
WholeCompositeBSerialized visit(CompositeB compositeB);
WholeLeafSerialized visit(Leaf leaf);
}
class SerializableComponentVisitor implements ComponentVisitor{
@Override
public WholeCompositeASerialized visit(CompositeA compositeA) {
WholeCompositeASerialized wcas = new WholeCompositeASerialized();
wcas.serializedChildren = compositeA
.getComponents()
.stream()
.map(c -> c.accept(this))
.collect(Collectors.toList());
wcas.content = compositeA.getCompositeData();
return wcas;
}
@Override
public WholeCompositeBSerialized visit(CompositeB compositeB) {
WholeCompositeBSerialized wcbs = new WholeCompositeBSerialized();
wcbs.serializedChildren = compositeB
.getComponents()
.stream()
.map(c -> c.accept(this))
.collect(Collectors.toList());
wcbs.content = String.valueOf(compositeB.getCompositeData());
return wcbs;
}
@Override
public WholeLeafSerialized visit(Leaf leaf) {
WholeLeafSerialized wls = new WholeLeafSerialized();
wls.content = Arrays.toString(leaf.getLeafData());
return wls;
}
}
interface Visitable{
Object accept(ComponentVisitor visitor);
}
如果我使用 instanceof
这是执行相同操作的代码:
class SerializerUsingInstanceOf {
Object decide(Component component){
if(component instanceof CompositeA){
return serialize((CompositeA)component);
}
else if(component instanceof CompositeB){
return serialize((CompositeB)component);
}
else{
return serialize((Leaf)component);
}
}
WholeCompositeASerialized serialize(CompositeA compositeA) {
WholeCompositeASerialized wcas = new WholeCompositeASerialized();
wcas.serializedChildren = compositeA
.getComponents()
.stream()
.map(this::decide)
.collect(Collectors.toList());
wcas.content = compositeA.getCompositeData();
return wcas;
}
WholeCompositeBSerialized serialize(CompositeB compositeB) {
WholeCompositeBSerialized wcbs = new WholeCompositeBSerialized();
wcbs.serializedChildren = compositeB
.getComponents()
.stream()
.map(this::decide)
.collect(Collectors.toList());
wcbs.content = String.valueOf(compositeB.getCompositeData());
return wcbs;
}
WholeLeafSerialized serialize(Leaf leaf) {
WholeLeafSerialized wls = new WholeLeafSerialized();
wls.content = Arrays.toString(leaf.getLeafData());
return wls;
}
}
我猜这里首选访问者,因为当我们添加新的 Component
时,我们还需要实现 Object accept(ComponentVisitor visitor)
方法 - 所以我们不能忘记我们需要一个代码来序列化这个新组件。如果我们在使用 instanceof
时也这样做,我们可能会忘记将其添加到该检查中。
现在 - 我的问题是 - 有什么方法可以摆脱丑陋的 Object
return 输入 Object accept(ComponentVisitor visitor)
方法签名?我想到的唯一其他选择是使用一些标记接口(例如 interface SerializedComponent {}
),然后让所有序列化程序 类 像这样 class WholeCompositeASerialized implements SerializedComponent
实现该空接口,但它仍然没有似乎是对的。
我认为正确的方法是在这里使用泛型。
例如https://onlinegdb.com/r1m5Eg4DP
public class Main {
public static void main(String []args){
ComponentVisitor<SerializedComponent> serializer = new ComponentSerializer();
Component componentA = new ComponentA();
SerializedComponent serializedA = componentA.accept(serializer);
System.out.println(serializedA);
Component component = new ComponentB();
SerializedComponent serializedB = component.accept(serializer);
System.out.println(serializedB);
}
static interface Component {
public <V> V accept(ComponentVisitor<V> visitor);
}
static class ComponentA implements Component {
public <V> V accept(ComponentVisitor<V> visitor) {
return visitor.visit(this);
}
}
static class ComponentB implements Component {
public <V> V accept(ComponentVisitor<V> visitor) {
return visitor.visit(this);
}
}
static interface SerializedComponent {}
static class SerializedComponentA implements SerializedComponent {
}
static class SerializedComponentB implements SerializedComponent {
}
static interface ComponentVisitor<V> {
public V visit(ComponentA component);
public V visit(ComponentB component);
}
static class ComponentSerializer implements ComponentVisitor<SerializedComponent> {
public SerializedComponent visit(ComponentA component) {
return new SerializedComponentA();
}
public SerializedComponent visit(ComponentB component) {
return new SerializedComponentB();
}
}
}
您正在尝试 return 来自访问者的具体类型信息。这不是该模式的目的。访问者在内部封装(和处理)具体类型。
这里的解决方案是将 all 特定于 ComponentA
的逻辑(或您可能将其转换为的任何 A-specific 类型)移动到 visit(ComponentA)
方法,同样适用于 ComponentB
.
如果不想要Visitor的类型封装,那么另一种设计更合适,比如模式匹配。
评论评论...
public static void main(String[] args) {
// Using a concrete type here defeats the purpose of these patterns.
// Instead, program to an interface:
// Component c1 = new CompositeA("root");
CompositeA c1 = new CompositeA("root");
c1.addChild(new Leaf(new String[]{"leaf11", "leaf12"}));
CompositeA c2 = new CompositeA("composite1");
c2.addChild(new Leaf(new String[]{"leaf21", "leaf22"}));
c1.addChild(c2);
SerializableComponentVisitor scv = new SerializableComponentVisitor();
// Clients never invoke visit methods directly,
// because they do not have the type information to make these calls.
// A client would execute, c1.accept(scv)
WholeCompositeASerialized wcas1 = scv.visit(c1);
}