示例情况: 我有一个电视抽象超类。两个子类继承自它。这两个子类都有工厂方法来创建自己的遥控器。 Remote是一个超类,它有两个子类。遥控器可以改变他们各自的电视频道(在这种情况下,三星遥控器应该与任何三星电视一起使用)。
远程类有一个changeChannel方法接收电视和频道。我的问题是,有没有一种方法可以保持这个层次结构与它当前拥有的方法和参数,而不必使用条件逻辑使遥控器只能改变自己品牌电视的频道。我已经提供了以下代码。
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 :(得分:0)
一种可以确保来自通用API的共存类型层次结构的方法可以共享代码和该API但仍然只能与他们自己的特定实现一起使用marker interfaces和generics:
/**
* 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...
}
答案 1 :(得分:0)
工厂方法可以帮到你。来自GoF参考:
将它应用于电视创建遥控器的地方:
您不得在television
方法上使用changeChannel()
参数。这确实是您需要进行检查的原因。
这正是Collection.iterator()
的工作原理。此外,Java API中没有记录许多具体的Iterator
(它们是具体集合的内部类,请参阅How does the Java class ArrayList return an Iterator Object?)。
你可以在你的设计中采用类似的方法,并说遥控器的客户不需要知道它们是什么样的精确类,因为他们只是想用它们来改变频道。您可以使SamsungRemote
成为SamsungTV
的私有内部类,createRemote()
方法始终返回一个上传类型的Remote。