cari

Rumah  >  Soal Jawab  >  teks badan

设计模式 - 为什么很多人写 Java/Android 时,选择让同一个类实现多个接口,而不是用多个内部匿名类?

呃…… 标题不太好。让我在问题描述里解释一下。

让我以 Android 开发中一个简单的例子说明:在一个 Activity 中有多个可点击的按钮时,很多人会这么写:

public class ExampleActivity extends Activity implements OnClickListener {

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        findViewById(R.id.first_button).setOnClickListener(this);
        findViewById(R.id.second_button).setOnClickListener(this);
    }

    @Override
    public void onClick(final View v) {
        switch (v.getId()) {
            case R.id.first_button:
                // bla bla bla
                break;
            case R.id.second_button:
                // bra bra bra
        }
    }
    
}

事实上,Android 官方有些 sample 里面也是这么写的。然而在我看来,这么写代码是非常不优雅的,因为一个 OnClickListener 的实现,只应该关注和点击事件本身相关的内容,它的含义和 Activity 的含义是截然无关的,让同一个类继承/实现他们,会使得这个类的含义变得不清晰。同时,这样还给 ExampleActivity 类增加了一个 public 的方法,削弱了这个类的封闭性。

所以如果像下面这样,会好不少:

public class ExampleActivity extends Activity {

    private OnClickListener onClickListener = new OnClickListener() {
        @Override
        public void onClick(final View v) {
            switch (v.getId()) {
                case R.id.first_button:
                    // bla bla bla
                    break;
                case R.id.second_button:
                    // bra bra bra
            }
        }
    };

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        findViewById(R.id.first_button).setOnClickListener(onClickListener);
        findViewById(R.id.second_button).setOnClickListener(onClickListener);
    }
    
}

这样写体现了 composition over inheritance 的思想。它避免了上面的所有问题,看起来舒服得多。

不过,这样还是让阅读代码时很不方便——看到 onCreate 里面时,还不得不经常滚动到声明 onClickListener 的地方去,并且在 onClick 中艰难的寻找真正和某个特定按钮相关的代码。当然这两个问题之前那个版本也都无法避免。

另一件糟糕的事情是,不同按钮的 listener 逻辑很可能是相对独立的,放到同一个 onClickListener 里,还是很丑陋。

所以为了进一步避免这几个问题,我一向都是用下面这样的写法:

public class ExampleActivity extends Activity {

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        findViewById(R.id.first_button).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                // bla bla bla
            }
        });
        findViewById(R.id.second_button).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                // bra bra bra
            }
        });
    }
    
}

这样的话,不同逻辑间相对独立,看起来非常舒服,便于阅读,并且让我找回了写 JavaScript 的舒畅感觉(划掉)。

那么问题来了:为什么有的人不使用最后一种写法呢,倒反是使用第一种写法呢?

高洛峰高洛峰2888 hari yang lalu389

membalas semua(9)saya akan balas

  • 巴扎黑

    巴扎黑2017-04-17 18:02:20

    Saya juga bersetuju dengan cara penulisan yang kedua Anda telah menyebut kelebihannya, jadi saya tidak akan menerangkan secara terperinci. Tetapi saya selalu tertanya-tanya mengapa contoh rasmi Google ditulis dengan cara pertama Kemudian, saya melihat perenggan dalam dokumentasi Android, yang secara kasarnya menyatakan: Mencipta objek dalam Java sebenarnya sangat mahal menyebabkan program menjana banyak overhed tambahan. Itulah sebabnya Google memilih untuk menggunakan objek yang sama untuk melengkapkan semua pemantauan Ini terutamanya kerana prestasi peranti Android awal tidak begitu baik, dan mereka hanya boleh menyimpan prestasi pada butiran tersebut Sekarang, peranti tidak perlu terlalu mengambil berat ini, jadi menggunakan Kaedah kedua juga tidak berbahaya.

    balas
    0
  • PHP中文网

    PHP中文网2017-04-17 18:02:20

    Saya secara peribadi lebih suka cara penulisan terakhir, dan jika OnClickListener banyak yang perlu dilakukan, saya mungkin menulisnya sebagai kelas yang dinamakan secara berasingan.

    Walau bagaimanapun, terdapat banyak cara pertama untuk menulis, saya rasa salah satu sebabnya ialah contoh yang mengelirukan, kerana kod contoh biasanya agak kecil, jadi tidak ada masalah dalam menulis dengan cara ini, dan kod itu tidak akan menjadi. sangat panjang, tetapi dalam perniagaan sebenar, kod itu mungkin lebih. Sebab lain mungkin kerana sesetengah orang berpendapat bahawa kelas menulis terlalu berat. Sebenarnya, kelas menulis tidak semestinya lebih berat daripada kaedah menulis asas teori dan praktikal Beberapa orang telah melakukan analisis, jadi saya tidak akan mengatakan lebih banyak.

    Dalam C#, perwakilan digunakan untuk melaksanakan acara Klik butang yang berbeza, dan setiap perwakilan sepadan dengan kaedah XxxxButton_Click tertentu Borang semasa (jika ia adalah program WinForm, aplikasi ASP.NET adalah serupa). cara penulisan Ia diwarisi daripada VB/VC kuno Sudah tentu, hakikat bahawa Pereka UI mahu melakukan ini tidak boleh diketepikan. Disebabkan populariti Lambda, semakin ramai orang mula menggunakan kaedah penulisan ketiga yang serupa dengan poster asal, tetapi ia bukan antara muka, ia hanya Lambda - dan terdapat premis, tanpa menggunakan Pereka UI untuk menjana situasi kod.

    Kenapa bercakap tentang C#, kerana Java telah menyedari keunggulan Lambda, jadi ia juga telah melaksanakan Lambda, mensimulasikan delegasi C# dalam bentuk antara muka kaedah tunggal, jadi cara penulisan ketiga boleh menjadi lebih mudah.

    Namun, semuanya mempunyai dua sisi Lambda memberikan kemudahan tetapi juga membawa sedikit kesulitan, terutamanya apabila logiknya rumit. Oleh itu, untuk pemprosesan peristiwa dengan logik yang lebih kompleks, saya masih mengesyorkan menulis kelas pemprosesan yang berasingan, yang boleh menjadi pelaksanaan antara muka acara (seperti pelaksanaan OnClickListener), atau kelas pemprosesan perniagaan bebas (atau sekumpulan yang berkaitan). . Panggil dalam satu ayat dalam onClick (seperti new Business(params).Go())

    balas
    0
  • 怪我咯

    怪我咯2017-04-17 18:02:20

    Komposisi atas warisan
    Bagaimana anda memahami perkara ini? Adakah komposisi lebih baik daripada warisan? Kerana reputasi warisan yang buruk, semua orang kini menolak warisan secara awal apabila mereka melihatnya.
    Tetapi adakah ini benar-benar berlaku? Saya tidak bersetuju.
    Perhubungan objek dalam OO dibahagikan secara kasar kepada beberapa perhubungan, seperti perkaitan, pergantungan, gabungan, pengagregatan, pewarisan dan generalisasi.
    Maksudnya, hubungan antara objek adalah apa sahaja hubungan itu, secara tepat, tidak ada kombinasi kerana konsep pewarisan saya tidak tahu kerana pewarisan mudah dilaksanakan, jadi semua orang suka gunakan warisan untuk digunakan semula Sebenarnya, intipati Perkara di atas disebabkan oleh pengabstrakan objek yang tidak mencukupi.
    Jadi sesetengah orang hanya mengemukakan idea bahawa gabungan lebih baik daripada warisan untuk memudahkan pemikiran semua orang.

    Berbalik kepada soalan utama, mengapa Google melaksanakannya dengan cara ini? Dari perspektif perniagaan, kitaran hayat aktiviti akan berada dalam beberapa peringkat. Keseluruhan kitaran hayat objek dilaksanakan oleh Android Walau bagaimanapun, ia adalah reka bentuk yang sangat munasabah untuk mendedahkan beberapa perkara utama melalui templat penanya akan mempunyai idea sedemikian.

    balas
    0
  • 巴扎黑

    巴扎黑2017-04-17 18:02:20

    Ini adalah pemahaman mendalam warga asing tentang overhed program. Ia telah menembusi jauh ke dalam sumsum tulang.

    balas
    0
  • 巴扎黑

    巴扎黑2017-04-17 18:02:20

    Saya sentiasa menggunakan cara penulisan kedua Semasa mula belajar Android, saya menggunakan cara ketiga, tetapi jika pendengar mempunyai banyak kandungan, ia tidak kelihatan sangat bagus

    balas
    0
  • 怪我咯

    怪我咯2017-04-17 18:02:20

    Saya hanya menulis kelas tanpa nama apabila terdapat sangat sedikit pendengar, dan secara amnya melaksanakan antara muka Jika kod acara klik adalah besar, saya menulis kaedah berasingan dan melaksanakannya dalam onClick. Saya rasa logik kod ini akan lebih jelas dan kemas.

    balas
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 18:02:20

    Pemprosesan peristiwa abstrak ke dalam proses kemasukan, dan kemudian abstrakkannya ke antara muka biasa. Ini adalah konsep kelas, bukan khusus untuk perniagaan.
    Cara anda menulis nanti jelas khusus untuk konsep objek.

    Saya lebih terbiasa menulis seperti ini, ia adalah perniagaan khusus dan objek khusus, dan tidak perlu menjadikannya umum

    balas
    0
  • ringa_lee

    ringa_lee2017-04-17 18:02:20

    Untuk objek yang digunakan sekali, gunakannya tanpa nama!

    balas
    0
  • 天蓬老师

    天蓬老师2017-04-17 18:02:20

    Cuma kelas dalam akan menyimpan contoh kelas luar, yang boleh menyebabkan kebocoran memori dengan mudah
    Jadi dari segi prestasi, cara penulisan pertama lebih baik daripada cara penulisan kedua, dan cara kedua menulis adalah lebih baik daripada cara penulisan ketiga

    balas
    0
  • Batalbalas