“变量分配请求”对象设计

如何解决“变量分配请求”对象设计

| 我有多个不允许修改彼此字段的类,但是必须通过将请求对象添加到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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-