<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## [完全解耦](https://lingcoder.gitee.io/onjava8/#/book/10-Interfaces?id=%e5%ae%8c%e5%85%a8%e8%a7%a3%e8%80%a6) 當方法操縱的是一個類而非接口時,它就只能作用于那個類或其子類。如果想把方法應用于那個繼承層級結構之外的類,就會觸霉頭。接口在很大程度上放寬了這個限制,因而使用接口可以編寫復用性更好的代碼。 例如有一個類**Processor**有兩個方法`name()`和`process()`。`process()`方法接受輸入,修改并輸出。把這個類作為基類用來創建各種不同類型的**Processor**。下例中,**Processor**的各個子類修改 String 對象(注意,返回類型可能是協變類型而非參數類型): ~~~ // interfaces/Applicator.java import java.util.*; class Processor { public String name() { return getClass().getSimpleName(); } public Object process(Object input) { return input; } } class Upcase extends Processor { // 返回協變類型 @Override public String process(Object input) { return ((String) input).toUpperCase(); } } class Downcase extends Processor { @Override public String process(Object input) { return ((String) input).toLowerCase(); } } class Splitter extends Processor { @Override public String process(Object input) { // split() divides a String into pieces: return Arrays.toString(((String) input).split(" ")); } } public class Applicator { public static void apply(Processor p, Object s) { System.out.println("Using Processor " + p.name()); System.out.println(p.process(s)); } public static void main(String[] args) { String s = "We are such stuff as dreams are made on"; apply(new Upcase(), s); apply(new Downcase(), s); apply(new Splitter(), s); } } ~~~ 輸出: ~~~ Using Processor Upcase WE ARE SUCH STUFF AS DREAMS ARE MADE ON Using Processor Downcase we are such stuff as dreams are made on Using Processor Splitter [We, are, such, stuff, as, dreams, are, made, on] ~~~ **Applicator**的`apply()`方法可以接受任何類型的**Processor**,并將其應用到一個**Object**對象上輸出結果。像本例中這樣,創建一個能根據傳入的參數類型從而具備不同行為的方法稱為*策略*設計模式。方法包含算法中不變的部分,策略包含變化的部分。策略就是傳入的對象,它包含要執行的代碼。在這里,**Processor**對象是策略,`main()`方法展示了三種不同的應用于**String s**上的策略。 `split()`是**String**類中的方法,它接受**String**類型的對象并以傳入的參數作為分割界限,返回一個數組**String\[\]\*\*。在這里用它是為了更快地創建 \*\*String**數組。 假設現在發現了一組電子濾波器,它們看起來好像能使用**Applicator**的`apply()`方法: ~~~ // interfaces/filters/Waveform.java package interfaces.filters; public class Waveform { private static long counter; private final long id = counter++; @Override public String toString() { return "Waveform " + id; } } // interfaces/filters/Filter.java package interfaces.filters; public class Filter { public String name() { return getClass().getSimpleName(); } public Waveform process(Waveform input) { return input; } } // interfaces/filters/LowPass.java package interfaces.filters; public class LowPass extends Filter { double cutoff; public LowPass(double cutoff) { this.cutoff = cutoff; } @Override public Waveform process(Waveform input) { return input; // Dummy processing 啞處理 } } // interfaces/filters/HighPass.java package interfaces.filters; public class HighPass extends Filter { double cutoff; public HighPass(double cutoff) { this.cutoff = cutoff; } @Override public Waveform process(Waveform input) { return input; } } // interfaces/filters/BandPass.java package interfaces.filters; public class BandPass extends Filter { double lowCutoff, highCutoff; public BandPass(double lowCut, double highCut) { lowCutoff = lowCut; highCutoff = highCut; } @Override public Waveform process(Waveform input) { return input; } } ~~~ **Filter**類與**Processor**類具有相同的接口元素,但是因為它不是繼承自**Processor**—— 因為**Filter**類的創建者根本不知道你想將它當作**Processor**使用 —— 因此你不能將**Applicator**的`apply()`方法應用在**Filter**類上,即使這樣做也能正常運行。主要是因為**Applicator**的`apply()`方法和**Processor**過于耦合,這阻止了**Applicator**的`apply()`方法被復用。另外要注意的一點是 Filter 類中`process()`方法的輸入輸出都是**Waveform**。 但如果**Processor**是一個接口,那么限制就會變得松動到足以復用**Applicator**的`apply()`方法,用來接受那個接口參數。下面是修改后的**Processor**和**Applicator**版本: ~~~ // interfaces/interfaceprocessor/Processor.java package interfaces.interfaceprocessor; public interface Processor { default String name() { return getClass().getSimpleName(); } Object process(Object input); } // interfaces/interfaceprocessor/Applicator.java package interfaces.interfaceprocessor; public class Applicator { public static void apply(Processor p, Object s) { System.out.println("Using Processor " + p.name()); System.out.println(p.process(s)); } } ~~~ 復用代碼的第一種方式是客戶端程序員遵循接口編寫類,像這樣: ~~~ // interfaces/interfaceprocessor/StringProcessor.java // {java interfaces.interfaceprocessor.StringProcessor} package interfaces.interfaceprocessor; import java.util.*; interface StringProcessor extends Processor { @Override String process(Object input); // [1] String S = "If she weighs the same as a duck, she's made of wood"; // [2] static void main(String[] args) { // [3] Applicator.apply(new Upcase(), S); Applicator.apply(new Downcase(), S); Applicator.apply(new Splitter(), S); } } class Upcase implements StringProcessor { // 返回協變類型 @Override public String process(Object input) { return ((String) input).toUpperCase(); } } class Downcase implements StringProcessor { @Override public String process(Object input) { return ((String) input).toLowerCase(); } } class Splitter implements StringProcessor { @Override public String process(Object input) { return Arrays.toString(((String) input).split(" ")); } } ~~~ 輸出: ~~~ Using Processor Upcase IF SHE WEIGHS THE SAME AS A DUCK, SHE'S MADE OF WOOD Using Processor Downcase if she weighs the same as a duck, she's made of wood Using Processor Splitter [If, she, weighs, the, same, as, a, duck,, she's, made, of, wood] ~~~ > \[1\] 該聲明不是必要的,即使移除它,編譯器也不會報錯。但是注意這里的協變返回類型從 Object 變成了 String。 > > \[2\] S 自動就是 final 和 static 的,因為它是在接口中定義的。 > > \[3\] 可以在接口中定義`main()`方法。 這種方式運作得很好,然而你經常遇到的情況是無法修改類。例如在電子濾波器的例子中,類庫是被發現而不是創建的。在這些情況下,可以使用*適配器*設計模式。適配器允許代碼接受已有的接口產生需要的接口,如下: ~~~ // interfaces/interfaceprocessor/FilterProcessor.java // {java interfaces.interfaceprocessor.FilterProcessor} package interfaces.interfaceprocessor; import interfaces.filters.*; class FilterAdapter implements Processor { Filter filter; FilterAdapter(Filter filter) { this.filter = filter; } @Override public String name() { return filter.name(); } @Override public Waveform process(Object input) { return filter.process((Waveform) input); } } public class FilterProcessor { public static void main(String[] args) { Waveform w = new Waveform(); Applicator.apply(new FilterAdapter(new LowPass(1.0)), w); Applicator.apply(new FilterAdapter(new HighPass(2.0)), w); Applicator.apply(new FilterAdapter(new BandPass(3.0, 4.0)), w); } } ~~~ 輸出: ~~~ Using Processor LowPass Waveform 0 Using Processor HighPass Waveform 0 Using Processor BandPass Waveform 0 ~~~ 在這種使用適配器的方式中,**FilterAdapter**的構造器接受已有的接口**Filter**,繼而產生需要的**Processor**接口的對象。你可能還注意到**FilterAdapter**中使用了委托。 協變允許我們從`process()`方法中產生一個**Waveform**而非**Object**對象。 將接口與實現解耦使得接口可以應用于多種不同的實現,因而代碼更具可復用性。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看