将功能传递给方法,而无需对类进行进一步更改。

huangapple go评论76阅读模式
英文:

Pass in functionality to a method without any further changes to the class

问题

以下是翻译好的内容:

我有以下的逻辑,它在我迭代对象并替换字符串值(如果适用)时运行良好。

但我试图将其变得更通用:我希望“替换”逻辑来自外部。

这是因为我希望有灵活性,以根据需要添加更多的操作功能。

我不想每次都要进入这个类并修改它。相反,希望使其可配置。

是否有任何方法可以实现这一点?

例如,我可能想要另一个逻辑,如果值是字符串,我想将“hello”附加到字符串上。

想这样做:

private String addHello(String value) {
return value + "hello";
}

// 然后在解析方法中。
if (fieldValue instanceof String) {
field.set(obj, switchName((String) fieldValue));
field.set(obj, addHello((String) fieldValue)); // 插入新的hello逻辑
}

这意味着每次我都要修改这个类。并不完全遵循SOLID原则。

它应该是不可修改的。

我正在寻求如何将这个变为可配置,以便我可以停止触及以下实现,但仍然能够添加更多的逻辑到其中。

英文:

I have the following logic which works fine where I am iterating an object and replacing string values if applicable.

But I am trying to make this more generic: I want the replace logic to come externally.

It is because I want the flexibility to be able to add on more manipulation functionality as needed.

I don't want to keep coming into this class and modify it each time. Instead looking to make it configurable.

Is there any approach I could take to achieve this?

For example I may want another logic where if the value is a string, I want to append "hello" to the string.

I don't want to do this:

private String addHello(String value) {
    return value + "hello";
}

// then in the parse method. 
if (fieldValue instanceof String) {
    field.set(obj, switchName((String) fieldValue));
    field.set(obj, addHello((String) fieldValue)); // new hello logic inserted
}

This would mean I am amending the class every time. Not exactly following SOLID principle.

It should be closed for modifications.

I am looking for advice on how I could turn this into being configurable so that I can stop touching the following implementation, but still be able to add on further logic to it.

import org.apache.commons.lang.reflect.FieldUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;

@Component
public class Helper {

    @SuppressWarnings("unchecked")
    public void parse(Object obj) throws IllegalAccessException {
        if (obj == null) {
            return;
        }

        for (Field field : obj.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            int modifiers = field.getModifiers();
            Object fieldValue = FieldUtils.readField(obj, field.getName(), true);
            if (fieldValue instanceof String) {
                field.set(obj, switchName((String) fieldValue));
            }
            else {
                parse(fieldValue);
            }
        }
    }

    private String switchName(String value) {
        return value.replace("apple", "orange");
    }
}

答案1

得分: 1

只要替换引用String的字段,您可以传递一个 Function<String,String>

public void parse(Object obj, java.util.function.Function<String,String> replaceFn ) 
throws IllegalAccessException { ... }

如果您想更加通用,可以传递接受对象和字段的参数,并执行某些操作。将其定义为特定接口会更容易找到所有实现。

@FunctionalInterface
public interface IFieldReplacer {
    public void accept(Object o, Field f) throws IllegalAccessException;
}

public class MyFieldReplacerA implements IFieldReplacer {

    @Override
    public void accept(Object o, Field f) throws IllegalAccessException {

        // TODO 获取值,进行转换,然后设置它。

    }
}

public void parse(Object obj, IFieldReplacer fieldReplacer ) {
  ...
}

这两种方法都允许调用者传递lambda表达式。

英文:

If you just want to replace fields referencing a String, you could pass in a Function<String,String>.

public void parse(Object obj, 
   java.util.function.Function<String,String> replaceFn ) 
throws IllegalAccessException { ... }

If you want to be more general, you could pass in something that accepts an object and a field, and does something with it. Defining that as a specific interface makes it easier to find all implementations.

@FunctionalInterface
public interface IFieldReplacer {
	public void accept(Object o, Field f) throws IllegalAccessException;
}

public class MyFieldReplacerA implements IFieldReplacer {

	@Override
	public void accept(Object o, Field f) 
    throws IllegalAccessException {

		// TODO Get the value, transmogrify it, and set it.

	}
}

public void parse(Object obj, IFieldReplacer fieldReplacer ) {
  ...
}

Both of these allow the caller to pass in a lambda expression.

huangapple
  • 本文由 发表于 2023年4月10日 21:56:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75977751.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定