MVC有MVC1和MVC2的區(qū)別,它們的區(qū)別在于MVC1中用Model來(lái)通知View進(jìn)行改變,而MVC2中使用Controller來(lái)通知View.在桌面程序中一般采用MVC1,而Web程序多采用MVC2,這是因?yàn)閣eb程序中,Model無(wú)法知道View的原因.
在Swing程序中,我們通常采用讓View實(shí)現(xiàn)Observer接口,讓Model繼承Observable類來(lái)實(shí)現(xiàn)MVC1,而讓Controller把它們創(chuàng)建及連接起來(lái),具體代碼如下:

public class XXXControl
{
private XXXModel model = null;
private XXXView view = null;


public XXXControl()
{
model = new XXXModel();
view = new XXXView();
model.addObserver(view);
}

.
.
.
}
而Model進(jìn)過(guò)處理后得到了結(jié)果,它采用Observable的notifyObservers()方法來(lái)通知View進(jìn)行改變,而View的public void update(Observable o, Object arg)方法將相應(yīng)這一改變,它通過(guò)解析Observable類型的對(duì)象o得到處理結(jié)果,再進(jìn)行具體的表現(xiàn)層改變.
粗看起來(lái)MVC各司其職,很完美,但還有不和諧的隱患:
1.View必須知道解析Model,造成了二者的耦合.
2.View非得實(shí)現(xiàn)Observer接口,Model非得繼承Observable類,這個(gè)處理不是必要的.
3.這種模式只適合即時(shí)處理,即相應(yīng)很快的處理,對(duì)于耗時(shí)過(guò)程并不適合.
4.由于Model中數(shù)據(jù)眾多,很多時(shí)候我們還需要建立一個(gè)常量類來(lái)區(qū)分各種情況和決定View更新的地方,進(jìn)一步加重了類之間的耦合程度.
綜上,我覺(jué)得對(duì)于稍大的Swing程序,MVC2+線程回調(diào)方式更適合,它的主要處理是:
1.依然由Controller創(chuàng)建View和Model,它們擔(dān)負(fù)的職責(zé)也和原來(lái)一樣,但是View不實(shí)現(xiàn)Observer接口,Model不繼承Observable類,它們?cè)撛趺礃舆€是怎么樣,而讓Controller來(lái)充當(dāng)它們之間的中介者.
2.如果是即時(shí)處理,可以在Controller中添加事件處理時(shí)就直接寫(xiě)來(lái).如果是耗時(shí)處理,可以將View和Model的引用(或Model中元素的引用)傳遞給一個(gè)線程處理類,具體的運(yùn)算和界面反應(yīng)在線程處理類中完成.
下面是一個(gè)調(diào)用例子:
new FetchTablesThread(model.getDataSource(), view,schema).start();
下面是線程類的例子:

public class FetchTablesThread extends BaseThread
{
private static Logger logger = Logger.getLogger(FetchTablesThread.class);

private String schema;

public FetchTablesThread(DataSource dataSource, SqlWindowView view,

String schema)
{
super(dataSource, view);
this.schema = schema;
}


public void run()
{
OutputPanel outputPanel = view.getTabbedPanel().getInputOutputPanel().getOutputPanel();


try
{

if (dataSource.getDbtype().equals("mysql"))
{
// Specail Process for MySql
new FetchTables4MySqlThread(dataSource, view, schema).start();

} else
{
// Ordinary Process for other DB
List tables = dataSource.getTablesInSchema(schema);


if (tables.size() > 0)
{
// Find tables under schema
view.getCatalogTablesPanel().getMultiTable().refreshTable(
tables);

outputPanel.showText(true);
String text = "Find " + tables.size()
+ " tables under schema:" + schema
+ " successfully!";
outputPanel.appendOutputText(text);
logger.info(text);

} else
{
// Can't find tables under schema
outputPanel.showText(true);
String text = "Can't find any table under schema:" + schema;
outputPanel.appendOutputText(text);
logger.info(text);
}
}

} catch (Exception ex)
{
outputPanel.showText(true);
String text = "Can't find any table under schema:" + schema+" and errorMsg="+ex.getMessage();
outputPanel.appendOutputText(text);
logger.info(text);
}
}
}
這樣做有兩個(gè)好處一是使程序結(jié)構(gòu)松散化,適于修改,二是相對(duì)傳統(tǒng)的MVC2,Controller中事件處理的代碼也容易變得簡(jiǎn)單而清晰,可維護(hù)性更佳.
綜上,我認(rèn)為MVC2+線程回調(diào)方式是一種值得推薦的Swing桌面程序?qū)懛?
關(guān)于線程回調(diào)方式,您可以參考:
http://www.tkk7.com/sitinspring/archive/2007/06/28/126809.html關(guān)于MVC,您可以參考:
http://junglesong.yculblog.com/post.2665424.html