2015-09-26 55 views
0

示例情形: 我有一個電視抽象超類。兩個子類從它繼承。這兩個子類都有工廠方法來創建自己的遙控器。 Remote是一個超類,它有兩個子類。遙控器能夠改變他們各自的電視頻道(在這種情況下,三星遙控器應與任何三星電視工作)。如何在不使用實例或getClass的情況下檢查對象的類型()

遠程類有一個changeChannel方法接入電視和頻道。我的問題是,有沒有一種方法可以保持當前的方法和參數的層次結構,而不必爲遠程使用條件邏輯,只能改變自己品牌電視的頻道。我已經提供了下面的代碼。你可以確保一個共同的API共存型層次結構可能可以共享代碼&該API,但仍然只能用自己的特定實現工作

import java.util.*; 

public abstract class Television{ 
    private int channel; 

    public abstract Remote makeRemote(); 

    public int getChannel(){ 
     return channel; 
    } 

    public void setChannel(int c){ 
     channel=c; 
    } 
} 

import java.util.*; 


public class SamsungTelevision extends Television{ 
    private int channel; 

    public Remote makeRemote(){ 
     return new SamsungRemote(); 
    } 

} 

import java.util.*; 


public class SonyTelevision extends Television{ 
    private int channel; 

    public Remote makeRemote(){ 
     return new SonyRemote(); 
    } 

} 

import java.util.*; 


public abstract class Remote{ 

    public abstract void changeChannel(Television t,int channel); 
} 

import java.util.*; 


public class SamsungRemote extends Remote{ 

    public void changeChannel(Television t,int channel){ 
     t.setChannel(channel); 
     System.out.println("Samsung: Channel has been switched"); 
    } 

} 

import java.util.*; 


public class SonyRemote extends Remote{ 

    public void changeChannel(Television t,int channel){ 
     t.setChannel(channel); 
     System.out.println("Sony: Channel has been switched"); 
    } 
} 

import java.util.*; 


public class Driver{ 
    public static void main(String[] args){ 
     Television t = new SamsungTelevision(); 
     Television t1 = new SonyTelevision(); 
     Remote r=t.makeRemote(); 
     r.changeChannel(t,35); 
     System.out.println("Samsung current channel: " + t.getChannel()); 
     r.changeChannel(t1,37); 
     System.out.println("Sony current channel: " + t1.getChannel()); 
    } 
} 
+0

*而不必使用條件邏輯的遙控器只能改變自己品牌的電視頻道*? No. –

+0

有幾種方法可以解決這個問題。如果你通過一臺不同製造的電視機,你是否在尋找會導致編譯時錯誤的東西?你有多少可以混淆現有的類? – augray

+0

當前的代碼很好。你爲什麼需要這張支票?如果你想知道從哪個代碼獲得執行的className,可以使用一個只記錄日誌的方法:this.getClass()。getSimpleName(); –

回答

0

一種方法是使用marker interfacesgenerics

/** 
* Different manufacturers can extend this interface 
* to ensure compile-time compatibility of their products while 
* using standard APIs that use generics for type safety. 
*/ 
public interface Manufacturer { 

} 

/** 
* This interface marks products created by Samsung. 
*/ 
public interface Samsung extends Manufacturer { 

} 

/** 
* This interface marks products created by Sony. 
*/ 
public interface Sony extends Manufacturer { 

} 

public abstract class Television<M extends Manufacturer>{ 
    private int channel; 

    //this ensures that a television only makes a remote 
    //by the same manufacturer 
    public abstract Remote<M> makeRemote(); 

    public int getChannel(){ 
     return channel; 
    } 

    public void setChannel(int c){ 
     channel=c; 
    } 
} 

public class SamsungTelevision extends Television<Samsung>{ 
    private int channel; 

    public Remote<Samsung> makeRemote(){ 
     return new SamsungRemote(); 
    } 

} 


public class SonyTelevision extends Television<Sony>{ 
    private int channel; 

    public Remote<Sony> makeRemote(){ 
     return new SonyRemote(); 
    } 

} 


public abstract class Remote<M extends Manufacturer>{ 

    //this ensures that a remote only works with a remote 
    //by the same manufacturer 
    public abstract void changeChannel(Television<M> t,int channel); 
} 


public class SamsungRemote extends Remote<Samsung>{ 

    public void changeChannel(Television<Samsung> t,int channel){ 
     t.setChannel(channel); 
     System.out.println("Samsung: Channel has been switched"); 
    } 

} 


public class SonyRemote extends Remote<Sony>{ 

    public void changeChannel(Television<Sony> t,int channel){ 
     t.setChannel(channel); 
     System.out.println("Sony: Channel has been switched"); 
    } 
} 

public class Driver{ 
    public static void main(String[] args){ 
     Television<Samsung> t = new SamsungTelevision(); 
     Television<Sony> t1 = new SonyTelevision(); 
     Remote<Samsung> r=t.makeRemote(); 
     r.changeChannel(t,35); 
     System.out.println("Samsung current channel: " + t.getChannel()); 

     //generates a compile time error because r is a samsung remote and 
     //t1 is a Sony TV 
     //r.changeChannel(t1,37); 
     //System.out.println("Sony current channel: " + t1.getChannel()); 
    } 
} 

這很好,因爲它可以創建編譯時安全性。人們甚至不會意外編寫一個違反制造商兼容性約束的程序。

如果你想要做的事,可與任何化妝的電視工作,你仍然可以做到這一點:

public static <M extends Manufacturer> void doSomethingWithTVOfAnyMake(Television<M> tv){ 
     int myChannel = tv.getChannel(); 
     //do more stuff... 
    } 
+0

好吧,我明白了。因此,使用泛型和標記接口,您可以在編譯時定義應該使用哪個類。如果我在運行時嘗試使用帶有Sony遙控器的三星電視機,那麼我將遇到一個錯誤,因爲這兩種類型不應該在編譯時定義一起工作。那是對的嗎? –

+0

差不多。其實好的一點是,你不能嘗試使用三星電視與索尼遙控器,它甚至不會編譯。嘗試取消註釋'//r.changeChannel(t1,37);'上面的行,然後編譯 - 你應該得到一個錯誤。 – augray

+0

好吧,我明白了。謝謝 –

0

工廠方法會爲你做它。從四人幫參考:

Factory Method pattern

應用它放在遙控器通過電視發佈:

Factory method applied to TV code

你不能在changeChannel()方法使用television說法。這真的是你需要檢查的原因。

這正是Collection.iterator()的工作原理。此外,Java API中沒有記錄許多具體的Iterator(它們是具體集合的內部類,請參見How does the Java class ArrayList return an Iterator Object?)。

你可以在你的設計中採用類似的方法,並說遠程客戶不需要知道他們是什麼確切的類,因爲他們只是想用它們來改變渠道。您可以使SamsungRemoteSamsungTV的私有內部類,並且createRemote()方法始終返回上傳類型的Remote。

相關問題