Java 面向对象编程-有关设计和访问相关数据的问题

Java 面向对象编程-有关设计和访问相关数据的问题,java,oop,swing,user-interface,timer,Java,Oop,Swing,User Interface,Timer,假设您在a中有以下代码: 它的主要目标是倒计时并在基于Swing的GUI上显示。 计时器是游戏的一部分,用于决定谁是赢家,它会让最先找到解决方案的用户决定谁是赢家 Action updateClockAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { JLabel secLabel = m_GameApplet.GetJpanelStartNetGame().GetJ

假设您在a中有以下代码: 它的主要目标是倒计时并在基于Swing的GUI上显示。 计时器是游戏的一部分,用于决定谁是赢家,它会让最先找到解决方案的用户决定谁是赢家

Action updateClockAction = new AbstractAction() {

    public void actionPerformed(ActionEvent e) {

        JLabel secLabel = m_GameApplet.GetJpanelStartNetGame().GetJlabelSeconds();
        secLabel.setFont(new java.awt.Font("Lucida Handwriting", 1, 36));
        secLabel.setForeground(Color.red);
        secLabel.setText(Integer.toString(m_TimerSeconds));
        if (m_TimerSeconds > 0) {
            m_TimerSeconds--;
        } else if (m_TimerSeconds == 0) {
            m_Timer.stop();
            m_GameApplet.GetJpanelStartNetGame().GetJlabelSeconds().setText("0");
            m_GameApplet.GetJpanelStartNetGame().GetJbuttonFinish().setVisible(false);
            //Checking whether time ended for both players and no solution was recieved
            if (!m_WasGameDecisived) {
                System.out.println("Tie - No one had a solution in the given time");
            }
        }
    }
};
m_Timer  = new Timer(1000, updateClockAction);
现在,我在客户端实现中有两个主要包 A.GUI-保持所有swing JPanel等。 逻辑引擎

现在在LogicEngine中,我有一个名为GameManager的类,它应该管理和存储有关游戏的信息

我当前的实现大体如下: 我有一个
JpanelMainGame
,它在GUI包中
JpanelMainGame
包含
JPanelGameBoard
,其中包含
GameManger
的引用(或换句话说,包含)实例,该实例位于不同的包中—
logicsengine

所以我的问题是:

  • 上面所有的计时器定义代码应该放在哪里

    A.在
    JpanelMainGame
    中?(
    JpanelMainGame
    应该有一个对它的引用)

    B.在
    GameManager
    中作为游戏数据的一部分

  • 在您给出的每个解决方案中,我应该如何访问匿名内部类中的所有标签信息?因为我只能使用命令从外部类访问成员:
    OuterClass.this.member

  • 对当前设计的任何意见


  • 非常感谢

    我重复我在以下方面给出的答案:

    我强烈反对从实现的角度组织包,如控制器、数据等。我更喜欢按功能对包进行分组,即feature1、feature2等。如果某个功能相当复杂,需要大量的类,那么(并且只有在那时)我才会创建上面所述的子包,即,功能1.控制器、功能1.数据等


    不是用问题来回答问题,但是

    • 定时器多久使用一次
    • 定时器编码是通用的,还是特定于某一类
    如果计时器是通用的,那么我会说它属于LogicEngine包树的某个地方。但是,如果计时器只能在GUI元素中使用,则它属于GUI包树

    作为一个一般的经验法则(不要过于猛烈地鼓吹敏捷),您现在应该只编写有意义的代码,但不要害怕以后更改它

    示例:您正在代码中创建AbstractAction()类型的匿名内部类。如果只是简单地使用UpdateLockAction变量,这就很好了(尽管我避开了anon类)。但是,一旦您的编码导致您需要跨越UpdateLockAction的边界(通过OuterClass.this.member),那么我断言是时候进行一些重构了:提取这个内部类并使其成为一个完全限定的类。这样,您就可以对UpdateLockAction对象的内部状态进行适当的控制(使用cstr、getter等)

    编辑:添加了请求的示例

    public class Testing {
        private Timer timer; /* INIT this from somewhere.... */
    
        public void myFunction() {
        /* 60 Seconds */
        long countDownTimeSEC = 60; 
        /* convert to Miliseconds */
        long countDownTimeMS = 1000 * countDownTimeSEC; 
    
        /* Get ref to label */
        JLabel label = m_GameApplet.GetJpanelStartNetGame().GetJlabelSeconds(); 
    
        /* Set once */
        label.setFont(new java.awt.Font("Lucida Handwriting", 1, 36)); 
        label.setForeground(Color.red);
    
        /* Set initial time */
        label.setText(Long.toString(countDownTimeSEC)); 
    
        /* Get ref to button */
        JButton button = m_GameApplet.GetJpanelStartNetGame().GetJbuttonFinish(); 
    
        /* Set up post Count Down list */
        ArrayList<AbstractAction> actsWhenComplete = new ArrayList<AbstractAction>();
    
        /* instantiate countdown object */
        CountDownClockAction cdca = new CountDownClockAction(label, countDownTimeMS, actsWhenComplete);
        this.timer  = new Timer(1000, cdca);
    
        /* Now that we have a timer, add the post Count Down action(s) to the  post Count Down list */
        actsWhenComplete.add(new CountDownFinishAction(label, button, this.timer));
    
    
        /* Finally, kick off the timer */
        this.timer.start();
    }
    
    public static class CountDownClockAction extends AbstractAction {
        private static final long serialVersionUID = 1L;
        private final JLabel labelToUpdate;
        private final long startMS;
        private long currentMS;
        private long timeMark;
        private final ArrayList<AbstractAction> actionsToExeWhenComplete;
        private boolean actionsExedFlag;
    
        public CountDownClockAction(
                final JLabel labelToUpdate, 
                final long startMS, 
                ArrayList<AbstractAction> actionsToExeWhenComplete
        ) {
            super();
            this.labelToUpdate = labelToUpdate;
            this.startMS = startMS;
            this.currentMS = startMS;
            this.timeMark = 0;
            this.actionsExedFlag = false;
            this.actionsToExeWhenComplete = actionsToExeWhenComplete;
        }
    
        @Override
        public void actionPerformed(final ActionEvent e) {
            /* First time firing */
            if (this.timeMark == 0) 
                this.timeMark = System.currentTimeMillis();
    
            /* Although the Timer object was set to 1000ms intervals, 
             * the UpdateClockAction doesn't know this, nor should it
             * since > or < 1000ms intervals could happen to do the fact that
             * the JVM nor the OS have perfectly accurate timing, nor do they
             * have instantaneous code execution properties.
             * So, we should see what the *real* time diff is...
             */
            long timeDelta = System.currentTimeMillis() - this.timeMark;
    
            /* Allow for the label to be null */
            if (this.labelToUpdate != null)
                labelToUpdate.setText(Long.toString((long)(currentMS / 1000)));
    
            if (currentMS > 0) {
                currentMS -= timeDelta;
    
            } else if (currentMS <= 0 && this.actionsExedFlag == false) {
                /* Ensure actions only fired once */
                this.actionsExedFlag = true;
                /* Allow for the label to be null */            
                if (this.actionsToExeWhenComplete != null)
                    for (AbstractAction aa: this.actionsToExeWhenComplete)
                    aa.actionPerformed(e);
            }
    
            /* Finally, update timeMark for next calls */
            this.timeMark = System.currentTimeMillis();
        }
    }
    
    public static class CountDownFinishAction extends AbstractAction {
        private final JLabel labelToUpdate;
        private final JButton buttonToUpdate;
        private final Timer timerToStop;
    
        public CountDownFinishAction(
                JLabel labelToUpdate,
                JButton buttonToUpdate, 
                Timer timerToStop
        ) {
            super();
            this.labelToUpdate = labelToUpdate;
            this.buttonToUpdate = buttonToUpdate;
            this.timerToStop = timerToStop;
        }
    
        @Override
        public void actionPerformed(final ActionEvent e) {
            /* Perform actions, allowing for items to be null */
            if (this.labelToUpdate != null)
                this.labelToUpdate.setText("0");
    
            if (this.buttonToUpdate != null)
                    this.buttonToUpdate.setVisible(false);
    
                if (this.timerToStop != null)
                    this.timerToStop.stop();
            }
        }
    }
    
    公共类测试{
    私人计时器;/*从某处初始化此*/
    公共函数(){
    /*60秒*/
    长倒计时秒=60;
    /*转换为毫秒*/
    长倒计时毫秒=1000*倒计时秒;
    /*获取标签的引用*/
    JLabel=m_GameApplet.GetJpanelStartNetGame().GetJlabelSeconds();
    /*设置一次*/
    setFont(新java.awt.Font(“Lucida手写”,1,36));
    标签。设置前景(颜色。红色);
    /*设定初始时间*/
    label.setText(Long.toString(countdowntTimeSec));
    /*获取引用到按钮*/
    JButton button=m_GameApplet.GetJpanelStartNetGame().GetJbuttonFinish();
    /*设置post倒计时列表*/
    ArrayList actsWhenComplete=新建ArrayList();
    /*实例化倒计时对象*/
    CountDownClockAction cdca=新的CountDownClockAction(标签、countDownTimeMS、actsWhenComplete);
    this.timer=新定时器(1000,cdca);
    /*现在我们有了计时器,将post倒计时操作添加到post倒计时列表中*/
    actsWhenComplete.add(新的倒计时完成操作(标签、按钮、此计时器));
    /*最后,启动计时器*/
    this.timer.start();
    }
    公共静态类CountDownClockAction扩展了AbstractAction{
    私有静态最终长serialVersionUID=1L;
    私人最终JLabel labelToUpdate;
    私人最终长期启动;
    私人长线电话;
    私人长时标;
    私人最终ArrayList诉讼,如未完成;
    私有布尔操作sexedflag;
    公众倒数计时行动(
    最终JLabel标签日期,
    最后的长启动,
    ArrayList操作完成时的示例
    ) {
    超级();
    this.labelToUpdate=labelToUpdate;
    this.startMS=startMS;
    此.currentMS=startMS;
    这个时间标记=0;
    this.actionsExedFlag=false;
    this.actionstoexwhencomplete=actionstoexwhencomplete;
    }
    @凌驾
    已执行的公共无效行动(最终行动事件e){
    /*第一次射击*/
    如果(this.timeMark==0)
    this.timeMark=System.currentTimeMillis();
    /*虽然计时器对象设置为1000ms间隔,
    *UpdateLockAction不知道这一点,也不应该知道
    *因为>或<1000ms的间隔可能会发生以下情况:
    *JVM和操作系统都有非常精确的计时,它们也没有
    *具有即时代码执行属性。
    *所以,我们应该看看什么是“实时”差异。。。
    */
    long-timeDelta=System.currentTimeMillis()-this.timeMark;
    /*允许标签为空*/
    if(this.labelToUpdate!=null)
    labelToUpdate.setText(Long.toString((Long)(currentMS/1000));
    如果(当前毫秒>0){
    currentMS-=时间增量;
    }如果(现在)还可以,谢谢,但是你的v是什么