【Practical API Design学习笔记】组件定位和交互

中心思想是:模块间去耦合。

举例说明:

  随机显示一个经过扰乱处理的不规则单词,而用户则要将扰乱后的单词纠正为正确的单词。其中,一个类用来生成原始单词,一个业务逻辑层用来扰乱单词,还有一个用户界面模块负责将这个单词展示给用户看。定义接口如下:

public interface Scrambler {
  public String scramble(String word);
}
public interface WordLibrary {
  public String[] getWords();
}
public interface UI {
  public void display();
}
实现:
public abstract class Anagrams extends javax.swing.JFrame implements UI {
  protected abstract WordLibrary getWordLibrary();
  protected abstract Scrambler getScrambler();
  
  public void display() {
    initWord();
    setVisible(true);
  }
}
public final class Launcher {
  private static Class<? extends WordLibrary> wordLibrary;
  private static Class<? extends Scrambler> scrambler;
  private static Class<? extends UI> ui;
  private Launcher() {
  }
  public static void registerWordLibrary(Class<? extends WordLibrary> libraryClass) {
    wordLibrary = libraryClass;
  }
  public static void registerScrambler(Class<? extends Scrambler> scramblerClass) {
    scrambler = scramblerClass;
  }
  public static void registerUI(Class<? extends UI> uiClass) {
    ui = uiClass;
  }
  public static UI launch() throws Exception {
    WordLibrary w = wordLibrary.newInstance();
    Scrambler s = scrambler.newInstance();
    return ui.getConstructor(WordLibrary.class, Scrambler.class).newInstance(w, s);
  }
}
public class AnagramsWithConstructor extends Anagrams {
  private final WordLibrary library;
  private final Scrambler scrambler;
  public AnagramsWithConstructor(WordLibrary library, Scrambler scrambler) {
    this.library = library;
    this.scrambler = scrambler;
  }
  @Override
  protected WordLibrary getWordLibrary() {
    return library;
  }
  @Override
  protected Scrambler getScrambler() {
    return scrambler;
  }
}

  以上代码注册方式效率非常慢,特别是在要注册的模块非常多的情况,都需要在系统启动时就注册,注册多个模块,就会进行很多模块的编译连接,效率非常慢。

注册的通用做法:

很多注册代码都是相同的,需要将其提取出来:

private static Map<Class<?>,Object[]> instances = new LinkedHashMap<Class<?>,Object[]>();
public static void registerClass(Class<?> impl) {
  instances.put(impl, new Object[1]);
}
public static <T> T find(Class<T> whatType) {
  for (Map.Entry<Class<?>, Object[]> entry : instances.entrySet()) {
    if (whatType.isAssignableFrom(entry.getKey())) {
      if (entry.getValue()[0] == null) {
        try {
          entry.getValue()[0] = entry.getKey().newInstance();
        } catch (Exception ex) {
          throw new IllegalStateException(ex);
        }
      }
      return whatType.cast(entry.getValue()[0]);
    }
  }
  return null;
}


@Override
protected WordLibrary getWordLibrary() {
  try {
    if (wordLibrary == null) {
      String implName=System.getProperty("org.apidesign.anagram.api.WordLibrary");
      assert implName != null;
      Class<?> impl = Class.forName(implName);
      wordLibrary = (WordLibrary)impl.newInstance();
    }
    return wordLibrary;
  } catch (Exception ex) {
    throw new IllegalStateException(ex);
  }
}
@Override
protected Scrambler getScrambler() {
  try {
    if (scrambler == null) {
      String implName = System.getProperty("org.apidesign.anagram.api.Scrambler");
      assert implName != null;
      Class<?> impl = Class.forName(implName);
      scrambler = (Scrambler)impl.newInstance();
    }
    return scrambler;
  } catch (Exception ex) {
    throw new IllegalStateException(ex);
  }
}

配置文件有用XML的,比如Spring的配置文件:

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
  >
  <bean
    id="wordLibrary"
    class="org.apidesign.anagram.wordstatic.StaticWordLibrary"
  />
  <bean
    id="scrambler"
    class="org.apidesign.anagram.scramblersimple.SimpleScrambler"
  />
  <bean
    id="ui"
    class="org.apidesign.anagram.gui.AnagramsWithConstructor"
    autowire="autodetect"
  />
</beans>


转载于:https://my.oschina.net/tingzi/blog/137358

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值