淺談抽象與接口(含工廠、適配器、代理模式應用)

抽象類和接口抽象類

abstract class A{      // 是定義了一個抽象類

       publicstatic final String FLAG = "CHINA" ;  //全局常量

       privateString name = "Cym" ;    // 定義一個普通的屬性

       publicvoid setName(String name){

              this.name = name ;

       }

       publicString getName(){

              return this.name ;

       }

       publicabstract void print() ;           // 定義抽象方法

};
包含一個抽象方法的類稱爲抽象類,抽象方法是隻聲明而未實現的方法,所有的抽象方法必須使用abstract關鍵字聲明,所有的抽象類也需要abstract關鍵字聲明。



abstract class A{      // 是定義了一個抽象類

       publicstatic final String FLAG = "CHINA" ;  //全局常量

       privateString name = "Cym" ;       // 定義一個普通的屬性

       publicvoid setName(String name){

              this.name = name ;

       }

       publicString getName(){

              return this.name ;

       }

       publicabstract void print() ;           // 定義抽象方法

};

class B extends A{  // 繼承抽象類,因爲B是普通類,所以必須覆寫全部抽象方法

       publicvoid print(){

              System.out.println("FLAG = " +FLAG) ;

              System.out.println("姓名 = " + super.getName()) ;

       }

};


對於抽象類來將,不能直接實例化的操作,但是可以聲明,如果要使用抽象類,則必須依靠子類,抽象類是必須被子類繼承,而且被繼承的子類需要實現抽象中的全部抽象方法。


問題:

抽象類是否可以使用final關鍵字修飾呢?

抽象類必須被子類繼承。

被final修飾的類不能被繼承。

所以得出結論,抽象類不能使用final關鍵子修飾。

抽象類是否可以存在構造方法?

abstract classA{      // 是定義了一個抽象類

              public A(){

                     System.out.println("A、抽象類中的構造方法。") ;

              }

};

class B extendsA{  // 繼承抽象類,因爲B是普通類,所以必須覆寫全部抽象方法

              public B(){

                     super();

                     System.out.println("B、子類中的構造方法。") ;

              }

};

public classAbstractDemo03{

              public static void main(String args[]){

                     Bb = new B() ;

              }

};

抽象類中允許有構造方法,但是此構造方法不能直接調用的,是交給子類調用的,子類對象的實例化過程中,永遠是先調用父類中的構造方法。

抽象類就是比普通類多了一個抽象方法而已。


抽象類屬性如何初始化?

abstract class Person{

       privateString name ;              // 定義name屬性

       privateint age ;                     // 定義age屬性

       publicPerson(String name,int age){

              this.name = name ;

              this.age = age ;

       }

       publicvoid setName(String name){

              this.name = name ;

       }

       publicvoid setAge(int age){

              this.age = age ;

       }

       publicString getName(){

              return this.name ;

       }

       publicint getAge(){

              return this.age ;

       }

       publicabstract String getInfo() ;      // 抽象方法

};

使用super

class Student extends Person{

       privateString school ;

       publicStudent(String name,int age,String school){

              super(name,age) ;     // 指定要調用抽象類中有兩個參數的構造方法

              this.school = school ;

       }

       publicvoid setSchool(String school){

              this.school = school ;

       }

       publicString getSchool(){

              return this.school ;

       }

       publicString getInfo(){

              return      "姓名:" + super.getName()  +

                            ";年齡:" + super.getAge() +

                            ";學校:" + this.getSchool() ;

       }

};

public class AbstractDemo04{

       publicstatic void main(String args[]){

              Student stu = new Student("張三",30,"清華大學") ;

              System.out.println(stu.getInfo()) ;

       }

};


抽象類中的屬性如果要想初始化,則肯定還要依賴與構造方法。

接口

接口是一個特殊的類,在java中接口是由抽象方法和全局常量組成。

java中使用interface定義一個接口


interface A{            // 定義接口A

       publicstatic final String AUTHOR = "CYM" ;      //全局常量

       publicabstract void print() ;    // 抽象方法

       publicabstract String getInfo() ;      // 抽象方法

}

在此接口中定義兩個抽象方法,一個全局常量,那麼接口與抽象類一樣,需要有子類,那麼子類此時不再稱爲繼承類,而是實現類,通過implements關鍵字實現完成。


接口的方法和屬性永遠是pubic修飾符

默認是方法是abstract

屬性是 static final

既然接口從定義上已經明確了要求是由抽象方法和全局常量組成,那麼在接口定義的時候就可以簡化操作

interface A{            // 定義接口A

       StringAUTHOR = "Cym" ;   // 全局常量

       voidprint() ;    // 抽象方法

       StringgetInfo() ;      // 抽象方法

}


一個類是雖然值能繼承一個父類,但是一個類可以同時實現多個接口。

如果一個類既要實現接口又要繼承抽象類的話,則必須按照一下的形式完成。

Class 子類extends 抽象類 implements 接口A,接口B......{}

interface A{            // 定義接口A

       publicString AUTHOR = "CYM" ;       //全局常量

       publicvoid print() ; // 抽象方法

       publicString getInfo() ;   // 抽象方法

}

abstract class B{      // 定義抽象類B

       publicabstract void say() ;      // 定義抽象方法

}

class X extends B implements A{   // X類線繼承B類,再實現A接口

       publicvoid say(){

              System.out.println("HelloWorld!!!") ;

       }

       publicString getInfo(){

              return "HELLO" ;

       }

       publicvoid print(){

              System.out.println("作者:" + AUTHOR) ;

       }

};

public class InterfaceDemo04{

       publicstatic void main(String args[]){

              X x = new X() ;      // 實例化子類對象

              x.say() ;

              x.print() ;

       }

};

接口裏面的方法可以簡寫方法不寫abstract關鍵字,但是抽象類裏一定要修abstract關鍵字。


interface A{            // 定義接口A

       publicString AUTHOR = "CYM" ;       //全局常量

       publicvoid print() ; // 抽象方法

       publicString getInfo() ;   // 抽象方法

}

abstract class B implements A{       // 定義抽象類B,實現接口A

       publicabstract void say() ;      // 定義抽象方法

}

class X extends B{  // X類線繼承B

       publicvoid say(){

              System.out.println("HelloWorld!!!") ;

       }

       publicString getInfo(){

              return "HELLO" ;

       }

       publicvoid print(){

              System.out.println("作者:" + AUTHOR) ;

       }

};

public class InterfaceDemo05{

       publicstatic void main(String args[]){

              X x = new X() ;      // 實例化子類對象

              x.say() ;

              x.print() ;

       }

};

一個抽象類可以實現多個接口,但是一個接口不能繼承一個抽象類。


interface A{            // 定義接口A

       publicString AUTHOR = "CYM" ;       //全局常量

       publicvoid printA() ;      // 抽象方法

}

interface B{

       publicvoid printB() ;

}

interface C extends A,B{

       publicvoid printC() ;

}

class X implements C{    // X類線繼承B

       publicvoid printA(){

              System.out.println("AHello World!!!") ;

       }

       publicvoid printB(){

              System.out.println("BHello MLDN") ;

       }

       publicvoid printC(){

              System.out.println("CHello LXH") ;

       }

};

public class InterfaceDemo06{

       publicstatic void main(String args[]){

              X x = new X() ;      // 實例化子類對象

              x.printA() ;

              x.printB() ;

              x.printC() ;

       }

};

一個接口雖然不可以繼承一個抽象類,但是一個接口卻可以同時繼承多個接口。


對象多態性

接口和抽象類的基本概念完成了,下面最重要的就是對象的多態性,是整個java中最重要的一個部分,因爲有多態性的存在,纔可以讓程序變的更加靈活。

多態性是面向對象的最後一個特徵:

方法的重載和方法的覆寫實際上就屬於多態行的一種體現。

真正的多態性中還包含了一種爲對象多態性概念。

對象多態性主要指的是,子類和父類對象的相互轉換關係。

向上轉型:父類 父類對象 = 子類實例  --》自動完成

向下轉型:子類 子類對象 = (子類)父類實例 --》強制完成


   classA{

       publicvoid fun1(){

              System.out.println("1A --> public void fun1(){}") ;

       }

       publicvoid fun2(){

              this.fun1() ;

       }

};

class B extends A{

       publicvoid fun1(){  // 將方法覆寫了

              System.out.println("2B --> public void fun1(){}") ;

       }

       publicvoid fun3(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("3B --> public void fun3(){}") ;

       }

};

public class PolDemo01{

       publicstatic void main(String args[]){

              A a = new B() ;       // 發生向上轉型關係,子類實例 --> 父類實例

              a.fun2() ;

       }

};

   父類對象 = 子類實例(向上轉型)

   只能使用父類有的方法。(子類如果覆寫則使用子類覆寫的方法)

class A{

       publicvoid fun1(){

              System.out.println("1A --> public void fun1(){}") ;

       }

       publicvoid fun2(){

              this.fun1() ;

       }

};

class B extends A{

       publicvoid fun1(){  // 將方法覆寫了

              System.out.println("2B --> public void fun1(){}") ;

       }

       publicvoid fun3(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("3B --> public void fun3(){}") ;

       }

};

public class PolDemo02{

       publicstatic void main(String args[]){

              A a = new B() ;       // 發生向上轉型關係,子類實例 --> 父類實例

              B b = (B)a ;    // 發生向下轉型關係,強制

              b.fun3() ;

              b.fun2() ;

       }

};

   父類對象 = 子類實例

   子類對象 = (子類)父類對象(向下轉型)

class A{

       publicvoid fun1(){

              System.out.println("1A --> public void fun1(){}") ;

       }

       publicvoid fun2(){

              this.fun1() ;

       }

};

class B extends A{

       publicvoid fun1(){  // 將方法覆寫了

              System.out.println("2B --> public void fun1(){}") ;

       }

       publicvoid fun3(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("3B --> public void fun3(){}") ;

       }

};

public class PolDemo03{

       publicstatic void main(String args[]){

              A a = new A() ;

              B b = (B)a ;

              b.fun2() ;

       }

};

會產生ClassCastException,表示轉換異常,造成的根本原因是兩個沒有關係的類進行相互的對象操作。


觀察對象多態性的作用:

           假如:現在要設計一個方法,那麼此方法可以接受A類的所有子類的實例。

如果現在不使用對象多態性的概念完成

class A{

       public void fun1(){

              System.out.println("1、A類 -->public void fun1(){}") ;

       }

       public void fun2(){

              this.fun1() ;

       }

};

class B extends A{

       public void fun1(){  // 將方法覆寫了

              System.out.println("2、B類 -->public void fun1(){}") ;

       }

       public void fun3(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("3、B類 -->public void fun3(){}") ;

       }

};

class C extends A{

       public void fun1(){  // 將方法覆寫了

              System.out.println("4、C類 -->public void fun1(){}") ;

       }

       public void fun4(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("5、C類 -->public void fun4(){}") ;

       }

};

public class PolDemo04{

       public static voidmain(String args[]){

              fun(new B()) ;

              fun(new C()) ;

       }

       public static void fun(Bb){

              b.fun2() ;

              b.fun3() ;

       }

       public static void fun(Cc){

              c.fun2() ;

              c.fun4() ;

       }

};

以上的方式是通過重載完成,那麼使用以上方法完成會存在以上的缺點,如果現在A類的子類有N個,那麼方法就要重載N次,而且每次增加子類的時候都需要修改代碼本身。

所以,此時使用對象多態性就可以很好的解決此類問題,因爲所有的對象都會發生自動的向上轉型操作。

class A{

       public void fun1(){

              System.out.println("1、A類 -->public void fun1(){}") ;

       }

       public void fun2(){

              this.fun1() ;

       }

};

class B extends A{

       public void fun1(){  // 將方法覆寫了

              System.out.println("2、B類 -->public void fun1(){}") ;

       }

       public void fun3(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("3、B類 -->public void fun3(){}") ;

       }

};

class C extends A{

       public void fun1(){  // 將方法覆寫了

              System.out.println("4、C類 -->public void fun1(){}") ;

       }

       public void fun4(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("5、C類 -->public void fun4(){}") ;

       }

};

public class PolDemo05{

       public static voidmain(String args[]){

              fun(new B()) ;

              fun(new C()) ;

       }

       public static void fun(Aa){

              a.fun2() ;

       }

};


class A{

       public void fun1(){

              System.out.println("1、A類 -->public void fun1(){}") ;

       }

       public void fun2(){

              this.fun1() ;

       }

};

class B extends A{

       public void fun1(){  // 將方法覆寫了

              System.out.println("2、B類 -->public void fun1(){}") ;

       }

       public void fun3(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("3、B類 -->public void fun3(){}") ;

       }

};

class C extends A{

       public void fun1(){  // 將方法覆寫了

              System.out.println("4、C類 -->public void fun1(){}") ;

       }

       public void fun4(){  // 此操作爲子類自己定義的,父類中不存在

              System.out.println("5、C類 -->public void fun4(){}") ;

       }

};

public class PolDemo08{

       public static voidmain(String args[]){

              fun(new B()) ;

              fun(new C()) ;

       }

       public static void fun(Aa){

              a.fun2() ;

              if(a instanceof B){

                     B b = (B)a ;

                     b.fun3() ;

              }

              if(a instanceof C){

                     C c = (C)a ;

                     c.fun4() ;

              }

       }

};

如果要使用子類自身的方法爲了保證對象向下轉型操作正確,在操作前最好加上instanceof關鍵字判斷。

在繼承關係中,父類的設計很重要,只要父類的設計合理了,則代碼開發非常簡便。


抽象類的應用

從對象多態性的概念來看,子類爲父類實例化是一個比較容易的操作,以爲可以發生自動的向上轉型關係,那麼調用的方法永遠是被子類覆寫過的方法。

那麼,此時就可以利用此概念通過對象多態性爲抽象類實例化。

抽象類可以實現方法,當很多類有相同方法和並且相同實現的時候,我們就可以用抽象類。當然也可以覆寫。

抽象類本身最大的用處就是在於模版設計。

接口的應用

接口也可以像抽象類那樣通過多態性進行對象的實例化操作。

抽象類可以用於定義模版操作,但是接口呢?

接口實際上是作爲一個標準存在的。

接口不可以的實現方法,但很多類只要有相同方法操作的時候,我們就可以用接口作爲一種標準。

接口和抽象類適配器設計模式

正常情況下一個接口的子類要實現全部的抽象方法

interface Window{

       publicvoid open() ; // 打開窗口

       publicvoid close() ; // 關閉窗口

       publicvoid icon() ;  // 最小化

       publicvoid unicon() ;      // 最大化

}

Class MyWindow implements Window

在MyWindow類此時肯定要覆寫全部的抽象方法,但是現在希望可以根據自己的需要來選擇覆寫,那麼該怎麼實現?

用一個類先將接口實現了,但是所有的方法都屬於空實現,之後再繼承此類。

應該使用抽象類,因爲抽象類也不能直接使用。

interfaceWindow{

       public void open() ; // 打開窗口

       public void close() ; // 關閉窗口

       public void icon() ;  // 最小化

       public void unicon() ;      // 最大化

}

abstract classWindowAdapter implements Window{

       public void open(){}

       public void close(){}

       public void icon(){}

       public void unicon(){}

};

class MyWindowextends WindowAdapter{

       public voidopen(){

              System.out.println("打開窗口!");

       }

};

public classAdpaterDemo{

       public static void main(String args[]){

              Windowwin = new MyWindow() ;

              win.open();

       }

}

工廠設計模式

interface Fruit{

       publicvoid eat() ;

}

class Apple implements Fruit{

       publicvoid eat(){

              System.out.println("吃蘋果。。。") ;

       }

};

class Orange implements Fruit{

       publicvoid eat(){

              System.out.println("吃橘子。。。") ;

       }

};

Public class interDemo

Public staticvoid main(String args[]){

Fruit f = new Apple();

F.eat();

}

以上的程序如果開發的話是存在問題?

一直強調:主方法實際上就是一個客戶端。客戶端的代碼越簡單越好。

interface Fruit{

       publicvoid eat() ;

}

class Apple implements Fruit{

       publicvoid eat(){

              System.out.println("吃蘋果。。。") ;

       }

};

class Orange implements Fruit{

       publicvoid eat(){

              System.out.println("吃橘子。。。") ;

       }

};

class Factory{  // 工廠類

       publicstatic Fruit getFruit(String className){

              Fruit f = null ;

              if("apple".equals(className)){

                     f= new Apple() ;

              }

              if("orange".equals(className)){

                     f= new Orange() ;

              }

              return f ;

       }

};

public class InterDemo{

       publicstatic void main(String args[]){

              Fruit f = Factory.getFruit(args[0]) ;

              if(f!=null){

                     f.eat();

              }

       }

}

所有接口的實例化對象都是工廠類取得的。那麼客戶端調用的時候根據傳入的名稱不同,完成不同的功能。

代理設計模式

interface Give{

       publicvoid giveMoney() ;

}

class RealGive implements Give{

       publicvoid giveMoney(){

              System.out.println("把錢還給我。。。。。") ;

       }

};

class ProxyGive implements Give{  // 代理公司

       privateGive give = null ;

       publicProxyGive(Give give){

              this.give = give ;

       }

       publicvoid before(){

              System.out.println("準備:小刀、繩索、鋼筋、鋼據、手槍、毒品") ;

       }

       publicvoid giveMoney(){

              this.before() ;

              this.give.giveMoney() ;   // 代表真正的討債者完成討債的操作

              this.after() ;

       }

       publicvoid after(){

              System.out.println("銷燬所有罪證") ;

       }

};

public class ProxyDemo{

       publicstatic void main(String args[]){

              Give give = new ProxyGive(new RealGive());

              give.giveMoney() ;

       }

};

當兩個類同時實現一個接口,一個類需要另外一個類代理才能實現該功能,這就叫代理模式。

抽象類與接口的區別
  

NO

  

比較點



抽象類



接口



1



組成



抽象方法、普通方法、常量、變量、構造、方法、全局變量



抽象方法、全局常量



2



定義



Abstract



interface



3



子類



子類通過extends繼承抽象類



子類通過implements實現接口



4



限制



一個子類只能繼承一個抽象類



一個子類能夠同時實現多個接口



5



關係



一個抽象類可以實現多個接口

  

一個抽象類中可以包含多個接口



一個接口不能繼承一個抽象類

  

一個接口可以包含多個抽象類



6



設計模式



模版設計



工廠模式、代理模式



7



實例化



都是通過對象的多態性、通過子類進行對象實例化操作



8



實現限制



存在單繼承侷限



不存在單繼承侷限



9



特性






一個標準、一種能力


         

如果抽象類和接口同時都可以使用的話、優先接口,以爲接口可以避免單繼承的侷限。

抽象類包含接口

abstract class A{

       publicabstract void fun() ;

       interfaceB{     // 內部接口

              public void print() ;

       }

};

class X extends A{

       publicvoid fun(){

              System.out.println("****************");

       }

       classY implements B{

              public void print(){

                     System.out.println("===================");

              }

       };

};

public class TestDemo01{

       publicstatic void main(String args[]){

              A a = new X() ;

              a.fun() ;

              A.B b = new X().new Y() ;

              b.print() ;

       }

};

接口包含抽象類

interface A{

       publicvoid fun() ;

       abstractclass B{      // 內部抽象類

              public abstract void print() ;

       }

};

class X implements A{

       publicvoid fun(){

              System.out.println("****************");

       }

       classY extends B{

              public void print(){

                     System.out.println("===================");

              }

       };

};

public class TestDemo02{

       publicstatic void main(String args[]){

              A a = new X() ;

              a.fun() ;

              A.B b = new X().new Y() ;

              b.print() ;

       }

};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章