如何解决“变量分配请求”对象设计
| 我有多个不允许修改彼此字段的类,但是必须通过将请求对象添加到Main类的队列中来请求修改。在每个循环的最后,Main类将执行请求的修改。public class Main {
public static ClassA a = new ClassA();
public static ClassB b = new ClassB();
private static List<Request> requestQueue = new ArrayList<Request>(); // List holds all requests
public static void main(String args[]) {
while (true) {
a.tick();
b.tick();
for (Request r : requestQueue) {
r.field = r.value; // All requests are fulfilled
}
requestQueue.clear();
}
}
public static <ValueType> void addModificationRequest(ValueType field,ValueType value) {
requestQueue.add(new Request<ValueType>(field,value));
}
}
// Request Object
public class Request<ValueType> {
ValueType field;
ValueType value;
public Request(ValueType field,ValueType value) {
this.field = field;
this.value = value;
}
}
// Classes
public class ClassA {
String name = \"A\";
public void tick() {
Main.addModificationRequest(Main.b.name,\"NewNameB\"); // Try to change b name
}
}
public class ClassB {
String name = \"B\";
public void tick() {
// Nothing
}
}
我知道代码很乱,但这是到目前为止我想到的最简单的方法。有谁知道可以以更简单,更可靠的方式完成此工作的良好设计模式?
(注意:我必须以这种方式使用它,不可能让类直接相互修改。)
编辑:类将具有多个可修改的变量。我还需要确定是否有任何请求尝试修改相同的变量,因此我可以忽略一个或两个。
编辑:感谢所有的帮助,我真的很感激!我决定让类跟踪自己的修改。我还将使用一直使用的同一Request对象,因为它简单明了。再次谢谢你。
解决方法
也许这不适用于您的用例,但是您可以让对象自己跟踪待处理的修改,然后从您的主类进行调用,以自行修改实际的字段。
如果只需要set操作,那么跟踪修改就像在类中为每个字段保留一个额外的字段一样容易。例如,如果需要一系列算术运算,则可以使用一系列修改。
public class DelayedModificationField<T> {
private T field;
private T newValue;
public T get() { return field;}
public delayedSet(T value) {
if (newValue != null) throw new ConcurrentModificationException(\"error\");
newValue = value;
}
public void performSet() {
field = newValue;
newValue = null;
}
public ExampleClass {
private DelayedModificationField<String> myField = new DelayedModificationField<String>();
public void setMyField(String s) { myField.delayedSet(s);}
public String getMyField() { return myField.get();}
public void performSet() { myField.performSet();}
}
您的主类必须跟踪所有支持延迟修改的对象,并在每个刻度上对其调用performSet。使它们实现一个接口并将它们保存在列表中。
, 这是行不通的。我不知道您分配的确切参数,但我将使用单个方法void setField(ValueType newValue)
定义接口Modifiable
。然后,我将声明ClassA
和ClassB
以实现Modifiable
。最后,将Request
类重新定义为Modifiable
和ValueType
而不是两个ValueType
字段。您的队列循环将是:
for (Request r : requestQueue) {
r.modifiable.setField(r.value);
}
编辑:
这是对该方法的修改,可以扩展到多个字段:
interface Modifiable {
void setName(String newName);
void setAge(Integer newAge); // I wish
}
abstract class Request<ValueType> {
Modifiable object;
ValueType value;
public Request(Modifiable object,ValueType value) {
this.object = object;
this.value = value;
}
abstract void execute();
}
class RequestNameChange extends Request<String> {
public RequestNameChange(Modifiable object,String name) {
super(object,name);
}
void execute() {
object.setName(name);
}
}
// etc.
另一种方法是使用反射,但是我怀疑那不是您的任务。
, 尝试使用“好莱坞”模式-它采用“不给我们打电话,我们称呼您”样式,也就是使用“回调”代码。
像这样:
public static class Main {
public static ClassA a = new ClassA();
public static ClassB b = new ClassB();
private static List<Runnable> requestQueue = new ArrayList<Runnable>(); // List holds all requests
public static void main(String args[]) {
while (true) {
a.tick();
b.tick();
for (Runnable r : requestQueue) {
r.run(); // All requests are fulfilled
}
requestQueue.clear();
}
}
public static void addModificationRequest(Runnable runnable) {
requestQueue.add(runnable);
}
}
使用匿名类调用addModificationRequest:
Main.addModificationRequest(new Runnable() {
public void run() {
Main.b.name = \"NewNameB\";
}
});
请注意,如果在执行foreach循环时调用addModificationRequest,则此代码将抛出15。一种便宜的解决方法是将关键字synchronized
添加到addModificationRequest并使用类对象作为锁在同步块内执行循环+清除。
编辑:
要也传递该字段,以便您可以检查它,请尝试以下操作:
interface FieldUpdater extends Runnable
{
Field getField();
}
static class Main
{
public static ClassA a = new ClassA();
public static ClassB b = new ClassB();
private static List<FieldUpdater> requestQueue = new ArrayList<FieldUpdater>(); // List holds all requests
private static Set<Field> seenBefore = new HashSet<Field>();
public void main(String args[])
{
while (true)
{
a.tick();
b.tick();
for (FieldUpdater r : requestQueue)
{
if (seenBefore.contains(r.getField()))
{
continue; // Or do something else specific
}
seenBefore.add(r.getField());
r.run();
}
requestQueue.clear();
}
}
public synchronized static void addModificationRequest(FieldUpdater fieldUpdater)
{
requestQueue.add(fieldUpdater);
}
}
然后像这样调用您的方法:
Main.addModificationRequest(new FieldUpdater()
{
public void run()
{
Main.b.name = \"NewNameB\";
}
public Field getField()
{
return Main.class.getField(\"name\");
}
});
请注意,为清楚起见,我故意省略了处理可以从getField()引发的Exception的方法。同样,这不是一个好的代码设计,但是确实可以解决所声明的代码。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。