Complete Decoupling

本文探讨了使用接口而非具体类以增强代码复用性和灵活性的方法。通过策略模式和适配器模式的应用,展示了如何处理不同对象类型,实现更广泛的代码适用性。

Whenever a method works with a class instead of an interface, we are limited to using that class or its subclass. If we would like to apply the method to a class that isn't in that hierarchy, we're out of luck. An interface relaxes this constraint considerably. As a result, we can write more resuable code.

For example:

// interfaces/Applicator.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.

import java.util.*;

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

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

class Upcase extends Processor {
  @Override // Covariant return:
  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(" ")); // Since:
1.4
  }
}

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);
  }
}
/* Output:
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]
*/

Creating a method that behaves differently depending on the argument object you pass it is called the Strategy design pattern. The method contains the fixed part of the algorithm, and the Strategy contains the part that varies. The Strategy is the object you pass in, containing code. Here, the Processor object is the Strategy, and main() shows three different Strategies applied to the String s.

Then suppose we discover a set of electronic filters that seem like they might fit into our Applicator.apply() method:

// interfaces/filters/Waveform.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
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
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
package interfaces.filters;

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

  public Waveform process(Waveform input) {
    return input;
  }
}
// interfaces/filters/LowPass.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
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
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
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
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
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 has the same interface elements as Processor , but because it isn’t inherited from Processor—because the creator of the Filter class had no clue we might want to use it as a Processor —we can’t use a Filter with the Applicator.apply() method, even though it would work fine. Basically, the coupling between Applicator.apply() and Processor is stronger than it needs to be, and this prevents the Applicator.apply() code from being reused when it ought to be. Also notice that the inputs and outputs are both Waveforms. If Processor is an interface, however, the constraints are loosened enough you can reuse an Applicator.apply() that takes that interface. Here are the modified versions of Processor and Applicator:

// interfaces/interfaceprocessor/Processor.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
package interfaces.interfaceprocessor;

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

  Object process(Object input);
}
// interfaces/interfaceprocessor/Applicator.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
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));
  }
}

The first way we can reuse code is if client programmers can write their classes to conform to the interface, like this:

// interfaces/interfaceprocessor/StringProcessor.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// javac interfaces/interfaceprocessor/StringProcessor.java
// {java interfaces.interfaceprocessor.StringProcessor} or {java interfaces/interfaceprocessor/StringProcessor}
package interfaces.interfaceprocessor;

import java.util.*;

interface StringProcessor extends Processor {
  @Override // remove this works fine.
  String process(Object input); // [1]

  String S = // [2]
      "If she weighs the same as a duck, " + "she's made of wood";

  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 // Covariant return:
  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(" "));
  }
}
/* Output:
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] This declaration is unnecessary; the compiler will not complain if we remove it. However it does notate the covariant return change from Object to String.

[2] s is automatically static and final because it’s defined inside an interface.

[3] We can even define a main() inside an interface. // Please note this.

However, we are often in the situation of being unable to modify the classes. In the case of the electronic filters, for example, the library was discovered rather than created. In these cases, you can use the Adapter design pattern. In Adapter, we write code to take the interface we have and produce the interface we need, like this:

// interfaces/interfaceprocessor/FilterProcessor.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {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); // delegation
  }
}

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);
  }
}
/* Output:
Using Processor LowPass
Waveform 0
Using Processor HighPass
Waveform 0
Using Processor BandPass
Waveform 0
*/

In this approach to Adapter, the FilterAdapter constructor takes the interface we have—Filter—and produces an object that has the Processor interface we need. You might also notice delegation in the FilterAdapter class. Covariance allows us to produce a Waveform from process() rather than just an Object.

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/Applicator.java

3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/filters/Waveform.java

4. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/filters/Filter.java

5. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/filters/LowPass.java

6. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/filters/HighPass.java

7. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/filters/BandPass.java

8. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/interfaceprocessor/Processor.java

9. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/interfaceprocessor/Applicator.java

10. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/interfaceprocessor/StringProcessor.java

11. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/interfaces/interfaceprocessor/FilterProcessor.java

The LTC3107 represents an ultra-low input voltage step-up DC-DC converter and power management solution specifically engineered to extend battery life in low-power devices. By employing advanced energy harvesting techniques from micro-energy sources such as thermoelectric generators (TEGs), this device optimizes power distribution while minimizing battery depletion, thereby significantly enhancing operational longevity.This integrated circuit achieves dual functionality through intelligent energy management: when sufficient harvested energy becomes available, it seamlessly transitions from primary battery power to auxiliary system operation. The transition mechanism incorporates automatic voltage regulation that precisely matches the main battery voltage, ensuring uninterrupted power delivery during source switching. The device’s operational efficiency stems from its sophisticated pin architecture. The V$\text{AUX}$ pin serves dual purposes as both the rectifier output and IC power input, featuring 10µF capacitor decoupling and an integrated 4.3V clamping diode. Energy storage management is implemented through the V$\text{STORE}$ pin, which interfaces with a ground-connected bulk capacitor for excess energy retention during load fluctuations. Primary power regulation occurs at the V$\text{OUT}$ pin, requiring minimum 47µF decoupling capacitance for stable operation.Battery integration is facilitated through the V$\text{BAT}$ pin (2.0V-4.0V input range), which initiates device startup and maintains V$\text{OUT}$ regulation. Supplementary functions include a 2.2V low-dropout regulator output at V$\text{LDO}$ (requiring at least 2.2µF ceramic capacitance) and thermal management through the GND pin’s exposed thermal pad. The BAT-OFF pin provides critical feedback on energy sufficiency and battery engagement status. Transformer-coupled operation is achieved through three dedicated terminals: the SW pin connects directly to the primary winding, serving as the internal N-channel switch drain, while C1 and C2 interface with secondary winding capacitors to complete the charge pump and gate drive circuits. This comprehensive architecture enables efficient micro-energy harvesting while maintaining robust power delivery capabilities across variable operating conditions.根据以上内容生成一个表格包括各引脚名称总结引脚功能及是否需要旁路电容 提供英文内容表格latex代码
最新发布
03-08
"Decoupling of mode" (模式解耦)是指在某个系统或过程中,将不同的功能或模块从彼此紧密耦合的状态中解开,使得它们可以独立地操作或发展。这种解耦可以带来一系列的好处,包括提高系统的灵活性、可扩展性和可维护性。 模式解耦的好处之一是系统的灵活性。通过解耦不同的功能或模块,可以使得系统更容易进行修改或扩展。例如,在软件开发中,如果各个模块之间过于紧密耦合,当需要对其中一个模块进行修改时,可能会影响到其他模块的正常运行,从而增加了修改的难度。而通过解耦,可以降低这种影响,使得系统更加灵活,能够更快速地进行修改或适应变化。 另一个好处是系统的可扩展性。通过解耦模块,可以更方便地添加新的功能或模块,而不会对原有的系统产生太大的影响。例如,在一个电子商务网站中,如果模块之间的耦合度较高,添加一个新的支付方式可能需要对多个模块进行修改。而通过解耦,可以将支付模块与其他模块解耦,从而更容易地添加新的支付方式,提高系统的可扩展性。 此外,模式解耦还有助于系统的可维护性。当各个功能或模块相互独立时,对系统进行维护或修复时可以更加专注和有效。如果模块之间过于紧密耦合,一个小的问题可能会影响到整个系统,导致维护过程变得复杂和困难。通过解耦,可以将问题范围限定在一个模块内,使得维护工作更加高效。 总的来说,“decoupling of mode”是一种通过解开紧密耦合的模块或功能之间的关系,使得系统更加灵活、可扩展和可维护的方法。它在各种领域,包括软件开发、系统设计和工程管理等方面都有着广泛的应用和重要的价值。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值