外观(Facade)模式,同属于结构型设计模式,是一个看似简单,要说清楚却又不容易的模式。之所以这么说,是因为这个模式并没有一个定式。我试图很好的理解外观模式,看过不少网友的介绍,无非都是“外观模式定义一个更高层的接口,使子系统更容易使用”、“解耦”之类的,这确实是外观模式的作用。但我觉得理解起来还是很吃力。下面是我对外观模式的理解,就从网上常用的封装数据库jdbc开始:
public class DBCompare {
Connection conn = null;
PreparedStatement prep = null;
ResultSet rset = null;
try {
Class.forName( "<driver>" ).newInstance();
conn = DriverManager.getConnection( "<database>" );
String sql = "SELECT * FROM <table> WHERE <column name> = ?";
prep = conn.prepareStatement( sql );
prep.setString( 1, "<column value>" );
rset = prep.executeQuery();
if( rset.next() ) {
System.out.println( rset.getString( "<column name" ) );
}
} catch( SException e ) {
e.printStackTrace();
} finally {
rset.close();
prep.close();
conn.close();
}
}
上面是使用jdbc对数据库进行操作的最原始的办法。如果是使用多种数据库或者需要扩展新数据库的场景,这样的设计有一定的缺陷,不好扩展,针对不同的数据库,代码重复度很高…反正就是各种不爽。那么可以使用外观模式,将看上去复杂的jdbc调用隐藏起来,对外暴漏一个简洁的、统一的抽象层:
class Database{
public Oracle getOracleObject(String username,String password,String url){}
public SqlServer getSqlServerObject(String username,String password,String url){}
public MySql getMySqlObject(String username,String password,String url){}
}
上面说明的是外观模式用于定义一个更高层次的接口层。
外观模式也可以用于隐藏部分功能。在<<how tomcat works>>这本书中就几次提到外观模式,例如介绍process()方法:
1、process方法接收的参数类型为 HttpRequest 和 HttpResponse。方法签名如下:
public void process(HttpRequest request, HttpResponse response);
2、process 使用了 request 和 response 的外观类,并在调用了 servlet 的 service 方法后,再调用HttpResponse 的 finishResponse 方法。示例代码如下:
servlet = (Servlet) myClass.newInstance();
HttpRequestFacade requestPacade = new HttpRequestFacade(request);
HttpResponseFacade responseFacade = new
HttpResponseFacade(response);
servlet.service(requestFacade, responseFacade);
((HttpResponse) response).finishResponse();
这里之所以使用外观类,是因为,在HttpRequest和HttpResponse类中有部分属性或者方法,不希望在service()方法中被访问到,其实HttpRequestFacade和HttpResponseFacade分别是HttpRequest和HttpResponse的一个简化类。虽然这里外观类和原始类实现同样的接口,外观类只是原始类的简化,但是外观类不能继承原始类,否则service()方法中能通过上转,转换成原始类而访问被隐藏的部分。
“隐藏”是我对外观模式的应用场景的一种理解,不管是隐藏子系统的复杂性还是防止某种情况被访问到,欢迎拍砖~