亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

DDD - 復合聚合序列化 - 設計問題

DDD - 復合聚合序列化 - 設計問題

互換的青春 2023-08-16 10:00:13
我正在嘗試將 DDD 應用于一個 Java 項目。這是我偶然發現的問題:在域中,我有一個使用復合 OOP 模式實現的聚合。該聚合上的方法會生成一些需要序列化并通過線路發送的域對象。這些是我想到的選項:在我的域的應用程序服務部分中,我正在聚合,調用它的方法,并嘗試將結果序列化到 DTO。為了將其序列化為 DTO,我必須instanceof檢查當前節點是復合節點還是子節點,然后繼續序列化。由于instanceof代碼味道(正如我讀到的,它違反了打開/關閉原則等),我決定嘗試使用訪問者模式。為了應用訪問者模式,我的復合聚合必須實現訪問者,它將返回 DTO,然后 DTO 成為域層的一部分 - 這也不是一個好的設計(因為域應該只包含域概念,而 DTO 不屬于其中) 。DTO 序列化只是技術細節,不應該進入領域層。還有其他不違背這些設計原則的解決方案嗎?有沒有辦法在java中模擬重載方法的動態綁定(除了instanceof- 因為這可以解決我使用選項1的問題)?
查看完整描述

3 回答

?
小怪獸愛吃肉

TA貢獻1852條經驗 獲得超1個贊

如果訪問者具有通用返回類型,則訪問的類不會與該類型耦合。


public interface Node {

    <T> T accept(NodeVisitor<T> visitor);

}


public class ANode implements Node {

    @Override

    public <T> T accept(NodeVisitor<T> visitor) {

        return visitor.visit(this);

    }

}


public class BNode implements Node {

    @Override

    public <T> T accept(NodeVisitor<T> visitor) {

        return visitor.visit(this);

    }

}


public interface NodeVisitor<T> {

    T visit(ANode aNode);

    T visit(BNode bNode);

}


public class DtoNodeVisitor implements NodeVisitor<DTO> {

    @Override

    public DTO visit(ANode aNode) {

        return new DTO(); //use ANode to build this.

    }

    @Override

    public DTO visit(BNode bNode) {

        return new DTO(); //use BNode to build.

    }

}

ANode并且BNode對這里一無所知DTO。


查看完整回答
反對 回復 2023-08-16
?
九州編程

TA貢獻1785條經驗 獲得超4個贊

首先,在第 2 點中我不明白:


我的復合聚合必須實現訪客


我想到的第一個問題是,為什么?您不能將訪問者聲明為接口,并將實現作為聚合的輸入參數傳遞嗎?


有沒有辦法在java中模擬重載方法的動態綁定(除了instanceof - 因為這可以解決我使用選項1的問題)?


是的,您可以使用反射來做到這一點,但真正的問題是,您想使用它們嗎?


我認為答案取決于您需要管理多少案例以及它們發生變化的頻率?


如果您有“可管理”數量的不同案例,則解決方案instanceof可以是一個很好的交易:


public Something myMethod(Entity entity){

    if (entity instanceof AnEntity){

         //do stuffs

    else if (entity instanceof AnotherEntity){

         //do something else

    ...

    else {

         throw new RuntimeException("Not managed " + entity.getClass().getName());

    }

}

否則,當您有更多情況并希望將代碼拆分為自己的方法時,您可以使用 Java 來完成MethodHandle,讓我發布一個用法示例:


package virtualmethods;


import java.lang.invoke.MethodHandles;

import java.lang.invoke.MethodType;


public class MyObject {


    public String doStuffs(Object i) throws Throwable {

        try {

            final MethodType type = MethodType.methodType(String.class, i.getClass());

            return (String) MethodHandles.lookup()

                .findVirtual(getClass(), "doStuffs", type)

                .invoke(this, i);

        } catch (NoSuchMethodException e) {

            throw new RuntimeException("Not managed " + i.getClass().getName(), e);

        }

    }


    private String doStuffs(Integer i) {

        return "You choose " + i;

    }

    private String doStuffs(Boolean b) {

        return "You choose boolean " + b;

    }

}

然后使用它:


package virtualmethods;


public class Main {


    public static void main(String[] args) throws Throwable {


        MyObject object = new MyObject();


        System.out.println("Integer => " + object.doStuffs(5));

        System.out.println("Boolean => " + object.doStuffs(true));

        try {

            System.out.println("String => " + object.doStuffs("something"));

        }

        catch (Throwable e) {

            System.out.println("KABOOM");

            e.printStackTrace();

        }

    }


}

獲取an 的公共方法將查找以結果命名的方法并作為類中的輸入(更多信息請參見此處)。 使用這種方式,您可以在運行時分派方法(使用重載是在編譯時靜態鏈接)。但這兩種方法都存在一個問題,即您無法確定您將管理第一種情況和/或第二種情況中擴展/實現的所有類型,兩種解決方案都有一個或一個來檢查何時傳遞非托管類型到方法。MyObjectObjectdoStuffsStringi.getClass()MyObject

EntityObjectelsecatch

百分百確定您正在管理所有類型只能使用@jaco0646提出的解決方案來實現,據我所知,它強制您管理所有類型,否則它將無法編譯??紤]到它需要的樣板數量,我只會在拋出會RuntimeException導致業務問題時使用,并且我不能保證它不會使用適當的測試來拋出(除此之外,我發現它非常有趣)。


查看完整回答
反對 回復 2023-08-16
?
一只名叫tom的貓

TA貢獻1906條經驗 獲得超3個贊

聽起來你把它過于復雜化了。如果您需要,typeof那么您的聚合不會返回有效的域對象。它返回的域對象太通用。為了解決這個問題,您可以將聚合方法分為兩種方法;一個返回 Child,另一個返回 Composite。然后,您的應用程序服務決定調用哪一個(如果可能)。

如果由于某種原因您需要聚合返回通用對象,我會重新考慮您選擇的設計。

另一個“黑客”是簡單地在域對象上放置一個屬性來指示它是復合對象還是子對象。我假設聚合會知道它是否是并且能夠準確地填充該屬性。


查看完整回答
反對 回復 2023-08-16
  • 3 回答
  • 0 關注
  • 195 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號