中心思想是:模块间去耦合。
举例说明:
随机显示一个经过扰乱处理的不规则单词,而用户则要将扰乱后的单词纠正为正确的单词。其中,一个类用来生成原始单词,一个业务逻辑层用来扰乱单词,还有一个用户界面模块负责将这个单词展示给用户看。定义接口如下:
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>