Java抽象類、接口與設(shè)計(jì)模式

一、抽象類(abstract class)

1. 定義:如果一個(gè)類沒有包含足夠多的信息來描述一個(gè)具體的對(duì)象,這樣的類就是抽象類.

  • 抽象類不能實(shí)例化,但是也能像普通類一樣在{}中定義成員變量、成員方構(gòu)造方法等。
  • 抽象方法:只聲明,不實(shí)現(xiàn)。具體的實(shí)現(xiàn)由繼承它的子類來實(shí)現(xiàn),也就是說,被abstract修飾的方法,方法名后直接跟一個(gè)分號(hào),如:
abstract public void show();
  • 一個(gè)類中含有抽象方法(被abstract修飾),那么這個(gè)類必須被聲明為抽象類(被abstract修飾)。
  • 構(gòu)造方法、類方法(用static修飾的)不能聲明為抽象方法。

2. 繼承抽象類:使用extends來繼承一個(gè)抽象類

  • 如果繼承于一個(gè)抽象類,就必須實(shí)現(xiàn)抽象類里面的抽象方法。
  • 如果不實(shí)現(xiàn)抽象方法,也可以把這個(gè)類定義為抽象類。
  • 只有抽象類的非抽象子類可以創(chuàng)建對(duì)象

abstract class BaseAndroidStudy {
    //定義一個(gè)代碼塊
    {
        System.out.println("鍛煉身體!");
    }

    //定義一個(gè)屬性 用于保存數(shù)據(jù)
    public String javaBook;
    public Dream dream;


    //提供構(gòu)造方法
        public BaseAndroidStudy(String javaBook,String dream){
            this.javaBook = javaBook;

            this.dream = new Dream();
            this.dream.dreamName = dream;
        }

    //定義一個(gè)靜態(tài)的常量
    public static final String CBOOK = "C Primier";


        //定義一個(gè)抽象方法  不需要實(shí)現(xiàn)  子類來實(shí)現(xiàn)
        abstract public void studyCLanguage();

        //定義一個(gè)普通方法  已經(jīng)確定了這個(gè)方法的具體實(shí)現(xiàn)
        public void studyJavaLanguage() {
            System.out.println("參加Java培訓(xùn)班");
        }

        //定義一個(gè)類 內(nèi)部類 用于管理每個(gè)人的理想 夢(mèng)想
        class Dream{
            private String  dreamName;

            public void show(){
                System.out.println("我的夢(mèng)想是:"+dreamName);
            }
        }

}

抽象類的使用:

class Student extends BaseAndroidStudy{
    String name;

    @Override
    public void studyCLanguage() {
        System.out.println("看書,看視頻");
    }

    public Student(String name,String bookName,String dream){
        super(bookName,dream);
        this.name = name;
    }
}


public class MyClass {
        public static void main(String[] agrs) {
          
            //1.顯示地創(chuàng)建一個(gè)類繼承于抽象類 創(chuàng)建這個(gè)類的一個(gè)對(duì)象
            Student xw = new Student("小王","java編程思想","成為高級(jí)工程師");


            //2.使用匿名類 只使用一次
            BaseAndroidStudy zs = new BaseAndroidStudy("java編程思想","成為高級(jí)工程師") {
                @Override
                public void studyCLanguage() {
                    System.out.println(".......");
                }
            };
        }
    }

二、接口(interface)

1. 定義:接口在java中是一個(gè)抽象類型,是抽象方法的集合。一個(gè)類通過繼承接口的方式,從而繼承接口的抽象方法。

  • 從定義是上看,接口是個(gè)集合,并不是類。類描述了屬性和方法,而接口只包含未實(shí)現(xiàn)的方法。接口和抽象類一樣不能被實(shí)例化,因?yàn)椴皇穷?。但是接口可以被?shí)現(xiàn)(impments關(guān)鍵字)。實(shí)現(xiàn)某個(gè)接口的類必須在類中實(shí)現(xiàn)該接口的全部方法。雖然接口內(nèi)的方法都是抽象的(和抽象方法很像,沒有實(shí)現(xiàn)),但是不需要abstract關(guān)鍵字。
  • 接口里面默認(rèn)的都是static final 常量, 默認(rèn)情況下不需要自己寫public static final,不能定義變量
  • 接口里面不能定義代碼塊
  • 接口里面不能定義構(gòu)造方法
  • 接口里面不能添加普通/對(duì)象/實(shí)例方法,必須是抽象的(不能實(shí)現(xiàn)), 默認(rèn)就是public abstract
interface TestInterface2 extends TestInterface{
    int I = 100;
    int COUNT = 100;

    void test();

    class Inner{
        int name;
        public void show(){
            System.out.println("內(nèi)部類");
        }
    }
}
  • 如果需要定義已經(jīng)有實(shí)現(xiàn)的方法,使用default
  • 接口里面可以定義內(nèi)部類 ,內(nèi)部類默認(rèn)public static
  • 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口 , 一個(gè)接口可以繼承多個(gè)接口
class GYLClass implements TestInterface2,TestInterface

2.繼承接口:一個(gè)接口能繼承另一個(gè)接口,和類之間的繼承方式比較相似。接口的繼承使用extends關(guān)鍵字,子接口繼承父接口的方法。

class GYLClass implements TestInterface2,TestInterface{

    @Override
    public void test() {
        TestInterface.Inner inner = new TestInterface.Inner();
        inner.show();
    }

    @Override
    public void test2() {

    }

    @Override
    public void test3() {

    }
}


//接口的使用
class Test{
    public static void main(String[] args){
        GYLClass gyl = new GYLClass();
        TestInterface2 t = new GYLClass();
    }
}

三、接口與抽象類的區(qū)別

  • 接口不能用于實(shí)例化對(duì)象。

  • 接口沒有構(gòu)造方法。

  • 接口中所有的方法必須是抽象方法。

  • 接口不能包含成員變量,除了 static 和 final 變量。

  • 接口不是被類繼承了,而是要被類實(shí)現(xiàn)。

  • 接口支持多繼承。

四、項(xiàng)目實(shí)戰(zhàn)(實(shí)現(xiàn)對(duì)按鈕的監(jiān)聽)

功能圖

1. 創(chuàng)建Activity模板(抽象類)

/**
 * 管理界面的抽象類 定義了一個(gè)界面創(chuàng)建到結(jié)束的模板
 */
public abstract class Activity{
    //保存這個(gè)界面的所有子視圖
    public ArrayList<View> childs = new ArrayList<View>();

    //抽象類不用實(shí)現(xiàn) 由子類實(shí)現(xiàn)

    //界面創(chuàng)建
    public abstract void OnCreate();

    //界面銷毀
    public abstract void OnDestroy();

   
}

2. 創(chuàng)建View管理所有視圖的顯示和事件監(jiān)聽


/**
 * 管理一個(gè)視圖顯示和事件監(jiān)聽
 * 什么情況下需要將一個(gè)父類做成一個(gè)抽象類
 * 1.不能直接創(chuàng)建這個(gè)類的對(duì)象
 * 2.這個(gè)類里面的某些方法 還不確定怎么實(shí)現(xiàn)
 *
 */
public class View {
    //所有視圖都擁有的屬性
    String backgroundColor;
    String borderColor;

    //記錄誰想監(jiān)聽這個(gè)事件
    //暫時(shí)不確定是誰要監(jiān)聽
    //但是要監(jiān)聽的人實(shí)現(xiàn)了這個(gè)接口  內(nèi)部接口
    OnClickListener listener;


    //所有的視圖都要監(jiān)聽事件
    //定義內(nèi)部接口
    public interface OnClickListener{
        //定義一套方法 約束外部使用這些方法來監(jiān)聽事件
         void onClick(View v);

    }

}

3. 創(chuàng)建主界面MainActivity

/**
 * 管理主界面(程序運(yùn)行起來第一個(gè)界面)
 */
public class MainActivity extends Activity implements View.OnClickListener{
  
    @Override
    public void OnCreate() {
        //主界面如何布局
      
    }


    @Override
    public void OnDestroy() {
        //銷毀之前需要做點(diǎn)什么事情
        System.out.println("......");
    }

4. 創(chuàng)建按鈕對(duì)象


/**
 * 創(chuàng)建一個(gè)按鈕類
 */
public class Button extends View{
    String title;
    String titleColor;

    public Button(String title,String titleColor){
        this.title = title;
        this.titleColor = titleColor;
    }
}

5. 創(chuàng)建一張圖片


/**
 * 顯示一張視圖
 */
public class ImageView extends View{
    String picture;

    public ImageView(String picture){
        this.picture = picture;
    }

}

6. 在主界面添加按鈕和圖片

 //主界面如何布局
        //添加一個(gè)按鈕
        button = new Button("分享","紅色");
        //添加一張圖片
        imageView = new ImageView("星空 ");

7. 實(shí)現(xiàn)控件添加到界?上的過程 抽象類Activity中 添加addChild方法

//將子控件添加到當(dāng)前界面上
    //接收的時(shí)候是用父類接收子類
    //當(dāng)要訪問子類內(nèi)容的時(shí)候 就要強(qiáng)制轉(zhuǎn)換為對(duì)應(yīng)的類型
    public void addChild(View v){
        if (v instanceof Button){
            Button btn = (Button)v;  //強(qiáng)制轉(zhuǎn)換
            System.out.println(btn.title+"按鈕顯示到界面上了");
        }

        if (v instanceof ImageView){
            ImageView iv = (ImageView)v;
            System.out.println(iv.picture+"圖片顯示到界面上了");
        }

        //保存子類控件
        childs.add(v);
    }

8. 將創(chuàng)建好的控件添加到界面上

 //將創(chuàng)建的控件添加到當(dāng)前界面
        addChild(button);
        addChild(imageView);

9. 事件監(jiān)聽 MainActivity實(shí)現(xiàn)接口 == MainActivity需要監(jiān)聽事件

//所有的視圖都要監(jiān)聽事件
    //定義內(nèi)部接口
    public interface OnClickListener{
        //定義一套方法 約束外部使用這些方法來監(jiān)聽事件
         void onClick(View v);

    }

10. 在MainActivity實(shí)現(xiàn)接?里?的?法

 //當(dāng)事件觸發(fā) 就會(huì)調(diào)用OnClick方法
    @Override
    public void onClick(View v) {
        System.out.println("按鈕被點(diǎn)擊了");
    }
}

11. 告訴按鈕 是誰要監(jiān)聽他的點(diǎn)擊事件

//如果一個(gè)控件需要監(jiān)聽事件就必須實(shí)現(xiàn)監(jiān)聽事件的接口
        //告訴按鈕誰在監(jiān)聽這個(gè)事件
        button.listener = this; //表示當(dāng)前類的一個(gè)對(duì)象

12. 使?匿名類給圖片添加事件監(jiān)聽器

//2.
        //給ImageView添加一個(gè)事件
        imageView.listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                System.out.println("圖片被點(diǎn)擊了");
            }
        };

13. View中事件接收觸摸事件的方法 用于獲取按鈕被點(diǎn)擊了

//用于控件接收觸摸事件
    public void getTouchEvent(){
        //調(diào)用監(jiān)聽者里面的OnClick方法
        listener.onClick(this);
    }

14. MainActivity中添加?法 模擬手觸摸屏幕 將觸摸的事件傳遞給按鈕或者圖片

 //模擬觸摸
    public void touch(){
        //將屏幕觸摸的事件傳遞給按鈕
        button.getTouchEvent();
        imageView.getTouchEvent();
    }

15. 外部使用

public class MyClass {
    public static void main(String[] args){
        //啟動(dòng)程序 創(chuàng)建界面
        MainActivity main = new MainActivity();

        //模擬觸摸
        main.touch();
    }
}

運(yùn)行結(jié)果:
運(yùn)行結(jié)果

計(jì)算代碼運(yùn)行時(shí)間:

public class MyClass {
    public static void main(String[]args){
        MyCode test = new MyCode();
        test.calculate();
    }
}
/**
 * 模板設(shè)計(jì)模式:
 *希望能創(chuàng)建一個(gè)模板
 * 使用這個(gè) 模板可以方便地測出代碼塊的執(zhí)行效率
 *
 */
abstract class TimeTemplate{
    //通過實(shí)現(xiàn)這個(gè)方法 獲得具體測量的代碼
    public abstract void code();

    //提供方法 實(shí)現(xiàn)測量
    public void calculate(){
        long start = System.currentTimeMillis();

        //測量的代碼
        code();

        long end = System.currentTimeMillis();

        System.out.println(end - start);
    }
}

class MyCode extends TimeTemplate{

    @Override
    public void code() {
        //寫自己的測試代碼
        int total = 0;
        for (int i = 0;i < 100000;i++){
            total += i;
        }
    }
}


五、心得體會(huì)

??這個(gè)demo下來自己對(duì)于代理設(shè)計(jì)模式,工廠設(shè)計(jì)模式等等模式還不是很懂,需要反復(fù)地練習(xí),加深理解。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容