将对象添加到数量较大的类的更好方法

时间:2019-07-16 20:07:59

标签: java

我正在尝试向代码中添加一些日志。

添加了一个新的类DataEntry:

class DataEntry
{
        private final String name;
    private final List<String> data;
    public String getName()
    {
        return name;
    }

    public List<String> getData()
    {
        return data;
    }   
    DataEntry(String name, List<String> data)
    {
        this.name = name;
        this.data = data;
    }
}

现在,我在另一个类中有一个方法需要传递一些参数,因此我在调用该类并对其进行初始化。

class Information
{

      protected void logData()
      {
        List<DataEntry> output = new ArrayList<>();
        // I have 10-12 like this entries, is there a better way to do this
        //Also is the tight coupling incorrect ? Any other way should i approach or is it fine ?
        DataEntry id = new DataEntry("id",Arrays.asList(getid()));
        DataEntry name = new DataEntry("name",Arrays.asList("abc","xyz"));
        //Same will need to add 20-30 entries here
        output.add(id );
        output.add(name );
      }
}

问题出在logData方法中,我有20-30个参数,所以有没有更好的方法来调用DataEntry类并将其添加到列表中?

2 个答案:

答案 0 :(得分:-1)

您可以使用此方法:

void log(String name, String... data) {
    DataEntry dataEntry = new DataEntry(name, Arrays.asList(data));
    // log your dataEntry
}

或者如果您真的想要列表:

void makeAndLog(List<DataEntry> list, String name, String... data) {
    DataEntry dataEntry = new DataEntry(name, Arrays.asList(data));
    list.add(dataEntry);
}

void logData() {
    List<DataEntry> list;
    makeAndLog(list, "id1", "1", "2");
    makeAndLog(list, "id5", "3", "4"); 
    // log your list
}

答案 1 :(得分:-1)

所以我提出了这个解决方案,但是它在所有情况下都不能使用,因为它有局限性和某些规则

  1. 我使用按方法名称的反射,我没有处理重载的方法
  2. 我假设您是通过POJO登录的,所以被调用的方法参数是此POJO字段的一部分(您可以将它们包装在pojo中以使其实现)
  3. 这还没有经过很好的测试,但是我相信这是一个改进的好开始

主要思想是如何无需手写就可以获取所有字段,现在您可以根据需要使用或重新设计它(从构造函数而不是方法中反映出来……)

在发布解决方案之前,我建议您针对这种用例使用AOP(aspect4j)更好。

我首先定义了一个记录器以类为中心的枚举,因此对于每个类,您都应该定义一个记录器逻辑,但是您可以使用我编写的一个通用逻辑。

这是经过简单测试的代码

我定义一个POJO,在其中包装参数或将其用作方法签名

public class User {
    private String name;
    private String username;
    private String email;

    public User(String name, String username, String email) {
        super();
        this.name = name;
        this.username = username;
        this.email = email;
    }

    public void mutate(String name, String username) {
        System.out.println("this is a mutation");
    }

    public void reflectAll(String name, String username, String email) {
        System.out.println("this is a full reflection");
    }

    public String getEmail() {
        return email;
    }

    public String getName() {
        return name;
    }

    public String getUsername() {
        return username;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

您添加的数据条目保持不变,是toString替代项可以在控制台上打印

public class DataEntry {
    private final String name;
    private final List<String> data;

    public String getName() {
        return name;
    }

    public List<String> getData() {
        return data;
    }

    DataEntry(String name, List<String> data) {
        this.name = name;
        this.data = data;
    }

    @Override
    public String toString() {
        return "DataEntry [name=" + name + ", data=" + data + "]";
    }


}

我使用枚举作为记录器,首先也许您会看到一种使用枚举的新方法(您可以使用一个类来做同样的事情),但是我说可能您会从中学习新的东西

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public enum DataEntryLogger {
    USER_CLASS{
        @Override
        List<DataEntry> log(Object o,String methodName) {
            List<DataEntry> userDataEntries = new ArrayList<DataEntry>();
            if( o instanceof User) {
                User toLog = (User) o;
                Optional<Method> oInvokedMethod = Arrays.asList(toLog.getClass().getMethods()).stream().filter((m) -> m.getName().equals(methodName)).findFirst();
                oInvokedMethod.ifPresent((invokedMethod)-> {
                    for(Parameter p : invokedMethod.getParameters()) {
                        System.out.println(p.getName());
                        try {
                            Field f = o.getClass().getDeclaredField(p.getName());
                            f.setAccessible(true);
                            userDataEntries.add(new DataEntry(p.getName(), Arrays.asList(""+f.get(o))));
                        System.out.println(f.get(o));
                        } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException
                                | SecurityException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                });
            }
            return userDataEntries;
        }
    },
    GENERIC{
        @Override
        List<DataEntry> log(Object o,String methodName) {
            List<DataEntry> dataEntries = new ArrayList<DataEntry>();

                Optional<Method> oInvokedMethod = Arrays.asList(o.getClass().getMethods()).stream().filter((m) -> m.getName().equals(methodName)).findFirst();
                oInvokedMethod.ifPresent((invokedMethod)-> {
                    for(Parameter p : invokedMethod.getParameters()) {
                        System.out.println(p.getName());
                        try {
                            Field f = o.getClass().getDeclaredField(p.getName());
                            f.setAccessible(true);
                            dataEntries.add(new DataEntry(p.getName(), Arrays.asList(""+f.get(o))));
                        System.out.println(f.get(o));
                        } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException
                                | SecurityException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                });

            return dataEntries;
        }
    };

    abstract List<DataEntry> log(Object o,String methodName);

}

最后这是一个小用例,如何使用它

public class Information {
    public static void main(String[] args) {
        DataEntryLogger logger = DataEntryLogger.USER_CLASS;
        User user = new User("taleb", "mhaleb", "talcorpdz@gmail.com");
        System.out.println("mutate methode invoked : " + logger.log(user, "mutate"));
        System.out.println("--------------------------------------------");
        System.out.println("--------------------------------------------");
        showUser(user);
        System.out.println("--------------------------------------------");
        System.out.println("--------------------------------------------");
        logger = DataEntryLogger.GENERIC;
        user = new User("genric", "genericUser", "generic@gmail.com");
        System.out.println("mutate methode invoked : " + logger.log(user, "mutate"));
        System.out.println("--------------------------------------------");
        System.out.println("--------------------------------------------");
        showUser(user);
    }

    public static void showUser(User u) {
        System.out.println("case of object used as dto");
        DataEntryLogger logger = DataEntryLogger.USER_CLASS;
        System.out.println("showUser methode invoked : " + logger.log(u, "reflectAll"));

    }
}

您应在Java编译器部分的项目设置中启用“存储有关方法参数的信息(可通过反射使用)”,这对于解析参数名称是必不可少的

  

参数名称应与字段相同

     

您可以根据需要编辑此作品并使其更加灵活