สร้างเหตุการณ์ที่กำหนดเองใน Java


193

ฉันต้องการทำสิ่งนี้ใน Java แต่ฉันไม่รู้วิธี:

เมื่อเหตุการณ์ "object 1 พูดว่า 'hello'" จะเกิดขึ้นดังนั้น object 2 จะตอบกลับเหตุการณ์นั้นโดยพูดว่า "hello"

ใครสามารถให้คำแนะนำหรือตัวอย่างรหัสแก่ฉันได้หรือไม่



คำตอบ:


421

คุณอาจต้องการที่จะมองเข้าไปในรูปแบบการสังเกตการณ์

นี่คือตัวอย่างรหัสบางส่วนเพื่อให้คุณเริ่มต้นได้ด้วยตนเอง:

import java.util.*;

// An interface to be implemented by everyone interested in "Hello" events
interface HelloListener {
    void someoneSaidHello();
}

// Someone who says "Hello"
class Initiater {
    private List<HelloListener> listeners = new ArrayList<HelloListener>();

    public void addListener(HelloListener toAdd) {
        listeners.add(toAdd);
    }

    public void sayHello() {
        System.out.println("Hello!!");

        // Notify everybody that may be interested.
        for (HelloListener hl : listeners)
            hl.someoneSaidHello();
    }
}

// Someone interested in "Hello" events
class Responder implements HelloListener {
    @Override
    public void someoneSaidHello() {
        System.out.println("Hello there...");
    }
}

class Test {
    public static void main(String[] args) {
        Initiater initiater = new Initiater();
        Responder responder = new Responder();

        initiater.addListener(responder);

        initiater.sayHello();  // Prints "Hello!!!" and "Hello there..."
    }
}

บทความที่เกี่ยวข้อง: Java: การสร้างเหตุการณ์ที่กำหนดเอง


มีเหตุผลที่ถูกต้องตามกฎหมายstackoverflow.com/suggested-edits/237242หรือไม่? มันแสดงให้เห็นถึงวิธีการทำสิ่งนี้กับ 2 คลาสเป็นคำถามที่ถามกัน
GlassGhost

2
จะเกิดอะไรขึ้นถ้าหลายเธรดกำลังสร้างเหตุการณ์ที่มาสิ่งนี้จะถูกซิงโครไนซ์อย่างถูกต้องหรือไม่
Mike G

ขึ้นอยู่กับความเห็นอกเห็นใจ ผู้ฟังแต่ละคนจะได้รับแจ้งตามลำดับที่ลงทะเบียน (Btw ฉันไม่เข้าใจสิ่งที่คุณหมายถึงโดยหลายหัวข้อที่นี่รหัสผู้ฟังจะได้รับการ exectued ในหัวข้อเดียวกันที่ทำให้เกิดเหตุการณ์ที่จะเกิดขึ้น..)
aioobe

8
@GlassGhost: มันถูกปฏิเสธเพราะโดยพื้นฐานแล้วมันเป็นการเขียนใหม่ทั้งหมด การแก้ไขคำตอบของคนอื่นนั้นดีถ้าพวกเขาแก้ไขการพิมพ์ผิดและการจัดรูปแบบและลิงก์ที่เสียหายและเช่นนั้น แต่พวกเขาไม่ควรเปลี่ยนแปลงเนื้อหาอย่างรุนแรง (มีข้อยกเว้นบางอย่างสำหรับการโพสต์ที่ระบุว่า "community wiki")
cHao

1
Java ไม่มีสิ่งในตัวสำหรับสิ่งนี้หรือไม่? ฉันชอบที่จะทำในรูปแบบนามธรรมไม่ได้ใช้สำหรับการวนซ้ำสำหรับทุกเหตุการณ์
Tomáš Zato - Reinstate Monica

27

สิ่งที่คุณต้องการคือการนำรูปแบบการสังเกตมาใช้ คุณสามารถทำได้ด้วยตัวเองโดยสมบูรณ์หรือใช้คลาส Java เช่นjava.util.Observerและjava.util.Observable


2
ใช้ซ้ำ - รีไซเคิล แต่ลองดูที่stackoverflow.com/questions/2380676/…
count0

21

มี 3 วิธีที่คุณอาจต้องการตั้งค่านี้:

  1. Thrower ด้านในของ Catcher
  2. Catcher ด้านในของ Thrower
  3. ThrowerและCatcherภายในคลาสอื่นในตัวอย่างนี้Test

ตัวอย่างการทำงานของ GITHUB ฉันกำลังอ้างอิงค่าเริ่มต้นของตัวเลือกที่ 3 เพื่อลองให้คนอื่นเพียงแค่ใส่เครื่องหมายOptionalบล็อก"" ของคลาสที่คุณต้องการเป็นหลักและตั้งค่าคลาสนั้นเป็น${Main-Class}ตัวแปรในbuild.xmlไฟล์:

4 สิ่งที่จำเป็นในการขว้างรหัสด้านข้าง:

import java.util.*;//import of java.util.event

//Declaration of the event's interface type, OR import of the interface,
//OR declared somewhere else in the package
interface ThrowListener {
    public void Catch();
}
/*_____________________________________________________________*/class Thrower {
//list of catchers & corresponding function to add/remove them in the list
    List<ThrowListener> listeners = new ArrayList<ThrowListener>();
    public void addThrowListener(ThrowListener toAdd){ listeners.add(toAdd); }
    //Set of functions that Throw Events.
        public void Throw(){ for (ThrowListener hl : listeners) hl.Catch();
            System.out.println("Something thrown");
        }
////Optional: 2 things to send events to a class that is a member of the current class
. . . go to github link to see this code . . .
}

2 สิ่งที่จำเป็นในไฟล์คลาสเพื่อรับเหตุการณ์จากคลาส

/*_______________________________________________________________*/class Catcher
implements ThrowListener {//implement added to class
//Set of @Override functions that Catch Events
    @Override public void Catch() {
        System.out.println("I caught something!!");
    }
////Optional: 2 things to receive events from a class that is a member of the current class
. . . go to github link to see this code . . .
}

6
@GlassGhost: ปัญหาคือว่าmainเป็นแบบคงที่และไม่มีสิ่งเช่นthisในฟังก์ชั่นคงที่ คุณต้องสร้างnew Catcher1()ที่ไหนสักแห่งและส่งต่ออินสแตนซ์นั้นแทน 1.5 ไม่อนุญาตthisในบริบทแบบคงที่เช่นกัน ฉันค่อนข้างแน่ใจว่ามันไม่เคยได้รับอนุญาต
cHao

6
@GlassGhost: รหัสที่ใช้อยู่ในคอนสตรัคที่ไม่ได้อยู่ในthis mainนั่นเป็นเหตุผลที่มันทำงาน ย้ายไปที่mainและฉันรับประกันว่าจะไม่ นั่นคือสิ่งที่ผู้คนพยายามบอกคุณและสิ่งที่คำตอบของคุณพยายามทำ ฉันไม่ให้อะไรกับ gitub ห่า - ฉันแคร์อะไรในนั้น และสิ่งที่คุณมีใน SO นั้นแตกหัก
cHao

7
@GlassGhost: ฉันไม่คิดว่าคำตอบของคุณไม่เพียงพอโดยรวม ปัญหาที่ฉันเห็นคือมันเป็นรหัสที่ไม่ทำงาน - คุณพยายามใช้thisจากmainซึ่งจะไม่รวบรวมใน Java รุ่นที่วางจำหน่าย หากส่วนนั้นอยู่ในตัวสร้างแทนหรือถ้าmainสร้างnew Catcher1()และใช้แทนแทนที่จะเป็นแบบthisนั้นก็ควรใช้งานได้แม้ใน 1.6+
cHao

6
@GlassGhost: "วิธีการที่ประกาศstaticถูกเรียกว่าวิธีการเรียนวิธีการเรียนมักจะเรียกโดยไม่ต้องอ้างอิงถึงวัตถุเฉพาะความพยายามที่จะอ้างอิงวัตถุปัจจุบันโดยใช้คำหลักthisหรือคำหลักsuperหรือการอ้างอิงพารามิเตอร์ประเภทของรอบใด ๆ การประกาศในเนื้อความของเมธอดคลาสส่งผลให้เกิดข้อผิดพลาดในการคอมไพล์เวลา " - JLS สำหรับ Java 5, §8.4.3.2
cHao

31
นี่เป็นหนึ่งในรูปแบบโค้ดที่แปลกประหลาดที่สุดเท่าที่ฉันเคยเห็น
เอริค

4

ต่อไปนี้ไม่เหมือนกัน แต่คล้ายกันฉันค้นหาตัวอย่างเพื่อเพิ่มการเรียกไปยังวิธีการอินเทอร์เฟซ แต่พบคำถามนี้ดังนั้นฉันจึงตัดสินใจเพิ่มตัวอย่างนี้สำหรับผู้ที่กำลังค้นหามันเช่นฉันและพบคำถามนี้ :

 public class MyClass
 {
        //... class code goes here

        public interface DataLoadFinishedListener {
            public void onDataLoadFinishedListener(int data_type);
        }

        private DataLoadFinishedListener m_lDataLoadFinished;

        public void setDataLoadFinishedListener(DataLoadFinishedListener dlf){
            this.m_lDataLoadFinished = dlf;
        }



        private void someOtherMethodOfMyClass()
        {
            m_lDataLoadFinished.onDataLoadFinishedListener(1);
        }    
    }

การใช้งานมีดังนี้:

myClassObj.setDataLoadFinishedListener(new MyClass.DataLoadFinishedListener() {
            @Override
            public void onDataLoadFinishedListener(int data_type) {
                }
            });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.