DesignPattern:在运行时创建未知实例成员的部分对象

时间:2019-07-12 22:43:07

标签: java oop design-patterns

当前,我有一个返回相当大的数据对象的端点。 对该类型的所有对象的此调用可以生成20MB的数据。但是,客户端并非总是需要对象中的所有信息,通常只需要一部分数据。我想为客户提供传递一些参数的选项,以确定他们需要对象的哪些部分。 例如,指定一个限制字段数组,每个字段本身都是对象上的一组实例成员,用户可以限制他们想要的对象数量。查看下图“对象”,限制字段值 r1 可能引用实例成员 a b

示例请求“ myurl / restrict = r1,r2”

MyObject(){
a;
b;
c;
d;
e;
f;
g;
h;
.... many more fields
}

因此,考虑到这一点,我创建了一个ENUM来建模限制字段和每个实例字段代表的实例成员的子集。 现在在数据库查询中,我想使用ENUM(s)值来确定我想要对象的哪些部分。

因此,选择查询将选择对象,并且可以通过调用所需的任何get / set方法来部分实例化该对象。我已经通过使用请求参数(即实例成员的分组)并在从DB返回的对象上进行反射以获取/设置要返回的对象的实例字段的方式,在查询端实现了这一点。

但是,我不确定除重构或为“较轻”对象创建新的端点以外,是否已经存在用于此问题的设计模式。我不想争论这种情况,我只想针对眼前的问题进行讨论,它反映了一种满足要求的有效方法,如果不是,为什么?还有其他选择。

我相信此解决方案可以轻松应对更改,如果实例成员更改或限制组需要调整,则仅枚举需要更新。其余层或数据层无需更改。但是我不确定会对性能产生影响,我只是在今天才实施了此功能,因此还无法进行基准测试。

我想真正的问题是;是否存在一种用于在运行时创建未知成员字段的部分对象的设计模式

下面是我如何实现以下选择方面的一种方法。

select(MyObj obj){
 //get all the restricted fields from the request
// Instantiate new object
// for each restriction field(i.e. instance member)
//         use reflection to invoke the set method of the new object(partial) passing the get method of the method argument(full object)
}

2 个答案:

答案 0 :(得分:0)

您可以为此使用对象映射器 员工->名称,ID,UID,地址

使用objectmapper的readvaluetotree 返回JsonNode / ObjectNode

选择密钥以构造新的json

Json = {“ name”:“ xyz”,“ id”:101,“ uid”:“ xoz”,“ address”:“ xqp street”}

删除不需要的键 jsonNode.remove或Delete键

然后使用jsonNode解析回对象 员工em = objectmapper.readValue(json,Employee.class)

答案 1 :(得分:0)

我想我可以利用Java8的功能方面为该任务找到一个非常好的方法。实际上,这也可以使用Java8之前的匿名类来实现。 我可以在Enum中利用这一点,并使用BiConsumer构造每个。 然后,当我遍历传入的参数时,可以实现该copy方法。 现在,我具有反射的行为,但没有性能影响。

public enum RestrictFields {
    R1((source, target) -> {
        target.setA(source.getA());
        target.setB(source.getB());
        target.setC(source.getC());
    }), 
    R2((source, target) -> {
        target.setD(source.D());
    });

    private final BiConsumer<MyObj, MyObj> copier;

    private RestrictFields (final BiConsumer<MyObj, MyObj> copier) {
        this.copier = copier;
    }

    public void copy(final MyObj source, final MyObj target){
        this.copier.accept(source, target);
    }
}

现在,当在select子句中时,我可以循环遍历传递的Enum值,并调用copy方法并基于此方法构建受限制的对象。

public Object select(MyObj source) {
        MyObj myobj = new MyObj ();
        if (!restrictedFields.isEmpty()) {
            // Instead of refelction here I can use the biconsumer in the enum

            for (RestrictFields field : restrictedFields) {
                field.copy(source, myobj);
            }
            return myObj;
        }
        return source;

    }