1. 程式人生 > >java基礎——從設計模式討論介面

java基礎——從設計模式討論介面

介面

1. 完全解耦

只要一個方法操作的是類而非介面,那麼就只能使用這個類及其子類。如果想使這個方法應用於不再此繼承結構中的某個類,那麼介面就可以在很大程度上放寬這種限制。例如:

public class Processor {
	public String name() {
		return getClass().getSimpleName();
	}

	Object process(Object input) {
		return input;
	}
}
public class Upcase extends Processor {
	String process
(Object input) { return ((String) input).toUpperCase(); } }
public class Downcase extends Processor {
	String process(Object input) {
		return ((String) input).toLowerCase();
	}
}
public class Spiltter extends Processor{
	String process(Object input) {
		return Arrays.toString(((String)input)
.split(" ")); } }
public class Apply {
	public static void process(Processor p,Object s) {
		System.out.println("Using Processor"+p.name());
		System.out.println(p.process(s));
	}
	public static String s ="He is still expected to be confirmed, due to the Republican majority in the Senate.";
	public
static void main(String[] args) { process(new Upcase(),s); process(new Downcase(),s); process(new Spiltter(),s); } }
Using ProcessorUpcase
HE IS STILL EXPECTED TO BE CONFIRMED, DUE TO THE REPUBLICAN MAJORITY IN THE SENATE.
Using ProcessorDowncase
he is still expected to be confirmed, due to the republican majority in the senate.
Using ProcessorSpiltter
[He, is, still, expected, to, be, confirmed,, due, to, the, Republican, majority, in, the, Senate.]

Apply.process()方法可以接受任何型別的Processor,並將其應用到一個Object物件上,然後列印結果。像本例這樣建立一個能夠根據所 傳遞引數物件 的不同而具有不同的方法被稱為策略設計模式

現在我們假設有一組電子濾波器,它們看起來好像適用於Apply.process()方法。

public class Waveform {
	private static long counter;
	private final long id = counter++;

	public String toString() {
		return " WaveFrom " + id;
	}
}

public class Filter {
	public String name() {
		return getClass().getSimpleName();
	}

	public Waveform process(Waveform input) {
		return input;
	}
}

public class LowPass extends Filter {
	double cutoff;

	public LowPass(double cutoff) {
		this.cutoff = cutoff;
	}
	public Waveform process(Waveform input) {
		return input;
	}
}

public class HighPass extends Filter {
	double cutoff;

	public HighPass(double cutoff) {
		this.cutoff = cutoff;
	}
	public Waveform process(Waveform input) {
		return input;
	}
}

public class BandPass {
	double lowCutoff, highCutoff;

	public BandPass(double lowCut, double highCut) {
		lowCutoff = lowCut;
		highCutoff = highCut;
	}
	public Waveform process(Waveform input) {
		return input;
	}
}

Filter與Processor具有相同的元素介面,但是因為它並非繼承自Processor,因此不能將Filter用於Apply.process()方法,主要是因為Apply.process()方法和Processor之間耦合過緊,已經超出了所需的程度。但是如果Processor是一個介面,那麼這些限制就會變得鬆動,下面是對Processor和Apply的修改。

public interface Processor {
	String name();
	Object process(Object input);
}
public class Apply {
	public static void process(Processor p, Object s) {
		System.out.println("Using Processor"+p.name());
		System.out.println(p.process(s));
	}
}
public abstract class StringProcessor implements Processor {
	public String name() {
		return getClass().getSimpleName();
	}
	public abstract String process(Object input);
	public static String s = "He is still expected to be confirmed, due to the Republican majority in the Senate.";
	public static void main(String[] args) {
		Apply.process(new Upcase(), s);
		Apply.process(new Downcase(), s);
		Apply.process(new Splitter(), s);
	}
}
public class Upcase extends StringProcessor{
	public String process(Object input) {
		return ((String) input).toUpperCase();
	}
}
public class Downcase extends StringProcessor {
	public String process(Object input) {
		return ((String) input).toLowerCase();
	}
}
public class Splitter extends StringProcessor{
	public String process(Object input) {
		return Arrays.toString(((String)input).split(" "));
	}
}
Using ProcessorUpcase
HE IS STILL EXPECTED TO BE CONFIRMED, DUE TO THE REPUBLICAN MAJORITY IN THE SENATE.
Using ProcessorDowncase
he is still expected to be confirmed, due to the republican majority in the senate.
Using ProcessorSplitter
[He, is, still, expected, to, be, confirmed,, due, to, the, Republican, majority, in, the, Senate.]

但是,經常碰到的情況是無法修改想要使用的類。例如,在電子濾波器的例子中,類庫是被發現而非建立的。在這種情況下,可以使用 介面卡設計模式 。介面卡中的程式碼將接受你所擁有的介面,併產生你所需要的介面,就像下面這樣:

public class FilterAdapter implements Processor {
	Filter filter;
	public FilterAdapter(Filter filter) {
		this.filter = filter;
	}
	@Override
	public String name() {
		return filter.name();
	}
	@Override
	public Object process(Object input) {
		return filter.process((Waveform) input);
	}
}
public class FilterProcessor {
	public static void main(String[] args) {
		Waveform w =new Waveform();
		Apply.process(new FilterAdapter(new LowPass(1.0)), w);
		Apply.process(new FilterAdapter(new HighPass(2.0)),w);
		Apply.process(new FilterAdapter(new BandPass(3.0,4.0)),w);
	}
}
Using ProcessorLowPass
 WaveFrom 0
Using ProcessorHighPass
 WaveFrom 0
Using ProcessorBandPass
 WaveFrom 0

FilterAdapter的構造器接受所擁有的Filter,然後生成所需要的Processor介面的物件。FiltterAdapter還使用到了代理的思想。

2. Java多重繼承

Java的依靠介面實現多重繼承,一個類可以 implements 多個介面,(注意:繼承類和繼承介面同時存在的時候,extends在implements之前),同時根據前幾章的向上轉型特性,當一個類繼承了多個介面的時候,也可以向上轉型為多種型別。

3. 通過繼承擴充套件介面

介面之間也存在繼承關係,通過繼承介面可以實現功能的擴充套件。

3.1 組合介面時的名字衝突

在打算組合的不同的不同介面中使用相同的方法名通常會造成程式碼可讀性的混亂,應該避免出現這種情況。

4. 適配介面

介面最吸引人之處就是允許同一個介面具有多個不同的具體實現,再簡單的情況下它的體現形式通常是一個接受介面型別的方法,而該介面的實現和向該介面傳遞的物件則取決於方法的使用者。因此介面最常用的就是策略設計模式。

最典型的例子就是Scanner類的構造器,它接受一個Readable介面。通過這種方式,Scanner可以作用於更多的型別。

Scanner(Readable source);

5.介面中的域

放入介面中的任何域都自動是static和final的訪問許可權是public,因此介面就成了一種成了一種很便捷的用來建立常量組的工具。

5.1 初始化介面中的域

在介面中定義的域不能是“空final”,但是可以被非常量初始化(表示式)。當然這些域不是介面中的一部分,它的值被存在該介面的靜態儲存區域內。

6.巢狀介面

介面可以巢狀在介面或其它類中。就像非巢狀介面一樣可以定義public , private 和 報訪問許可權。private的介面只能在定義它的類之內被實現(否則沒有意義)。巢狀在另一個類的介面 自動就是public的,當某類實現了該介面時不需要實現巢狀在內部的介面。

7. 介面與工廠

生成遵循某個介面的物件的典型方法就是 工廠模式 ,這與直接呼叫建構函式不同,我們在工廠物件呼叫的是建立方法,而工廠物件將生成介面的某個實現對的物件。

public interface Service {
	void methods1();
	void methods2();
}
public interface ServiceFactory {
	Service getService();
}
public class Implementation1 implements Service {
	Implementation1() {
	}
	@Override
	public void methods1() {
		System.out.println("Implementationa1 methods1");
	}
	@Override
	public void methods2() {
	System.out.println("Implementationa1 methods2");
	}
}
public class Implementation2 implements Service {
	Implementation2() {
	}
	@Override
	public void methods1() {
		System.out.println("Implementationa2 methods1");
	}
	@Override
	public void methods2() {
	System.out.println("Implementationa2 methods2");
	}
}
public class Implementtation1Factory implements ServiceFactory {
	@Override
	public Service getService() {
		return new Implementation1();
	}
}
public class Implementtation2Factory implements ServiceFactory {
	@Override
	public Service getService() {
		return new Implementation2();
	}
}
public class Factories {
	public static void serviceConsumer(ServiceFactory factory) {
		Service s = factory.getService();
		s.methods1();
		s.methods2();
	}
	public static void main(String[] args) {
		serviceConsumer(new Implementtation1Factory());
		serviceConsumer(new Implementtation2Factory());
	}
}