一、描述
外观模式又叫门面模式,就是对一个复杂的系统进行包装,该系统对外的接口统一由外观类提供。当一个复杂的系统需要对外提供接口时,就需要将对外提供的接口统一封装在一个外观类中供外系统使用。外观模式最大的特点就是将细粒度的对象包装成粗粒度的对象,应用程序通过访问这个外观对象来完成细粒度对象的调用。这样应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性。
总的来说,外观模式就是为子系统对外提供的一组接口,这组接口提供一个统一的界面,使得其它系统对该系统的访问都通过这个统一的界面来完成,该模式主要由3个部分组成:抽象外观类、实现抽象外观类的具体外观类和其它子系统类。
二、外观模式的优缺点
优点:外观模式通过提供一个统一的对外接口,避免了外部系统和子系统之间的直接联系,从而降低了系统间的依赖和复杂度。外观模式将复杂的细粒度的对象服务包装成简单的易使用的粗粒度的功能服务,方便了客户端的调用(例如java的API调用)。
缺点:限制类外部系统对子系统调用的灵活性,只能按照外观类中提供的方法对子系统进行调用。
三、源代码
本案例模拟java使用jdbc连接数据库,并进行数据查询和更新操作,输出查询结果集、释放数据库中的所有资源这几个子系统,我们通过一个抽象外观类定义了对外部系统的访问接口,并由两个具体的外观类实现了抽象外观类,对外提供一个统一的访问接口,从而方便客户端的访问。
1、子系统类
package tong.day5_2.facade;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
/**
* 从当前项目主目录下加载Config.properties数据库配置文件,初始化数据库配置信息
*/
public class ConfitgInfo {
private static String driver;
private static String url;
private static String user;
private static String password;
public void setConfig() {
try {
Properties properties = new Properties();
File file = new File(System.getProperty("user.dir") + "\\Config.properties");
properties.load(new FileInputStream(file));
driver = properties.getProperty("DatabaseDriver");
url = properties.getProperty("jdbcUrl");
user = properties.getProperty("DatabaseUser");
password = properties.getProperty("DatabasePassword");
System.out.println("driver:"+driver+",url:"+url+",user:"+user+",password:"+password);
} catch (Exception e) {
e.printStackTrace();
System.out.println("配置信息初始化失败!");
}
}
public static String getDriver() {
return driver;
}
public static void setDriver(String driver) {
ConfitgInfo.driver = driver;
}
public static String getUrl() {
return url;
}
public static void setUrl(String url) {
ConfitgInfo.url = url;
}
public static String getUser() {
return user;
}
public static void setUser(String user) {
ConfitgInfo.user = user;
}
public static String getPassword() {
return password;
}
public static void setPassword(String password) {
ConfitgInfo.password = password;
}
}
package tong.day5_2.facade;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 有关数据库连接和操作的所有功能
* @author tong
*
*/
public class DBConnection {
public Connection connection;
public Statement statement;
public ResultSet resultset;
/**
* 创建数据库连接
* @throws Exception
*/
public DBConnection() throws Exception {
Class.forName(ConfitgInfo.getDriver());
connection = DriverManager.getConnection(ConfitgInfo.getUrl(), ConfitgInfo.getUser(), ConfitgInfo.getPassword());
statement = connection.createStatement();
}
/**
* 查询数据库操作
*
* @param sql SELECT语句
* @return ResultSet 对象
* @throws Exception
*/
public ResultSet select(String sql) throws Exception {
resultset = statement.executeQuery(sql);
return resultset;
}
public ResultSet select(String table, String limit, int min, int max) throws SQLException {
String sql = "SELECT * FROM (SELECT A.* , ROWNUM RN FROM " + table + " A WHERE " + limit + " ) WHERE RN <= " + max + " AND RN >= " + min;
resultset = statement.executeQuery(sql);
return resultset;
}
/**
* 更新数据库操作
*
* @param sql INSERT ,DELETE,UPDATE 语句
* @throws Exception
*/
public void update(String sql) throws Exception {
statement.execute(sql);
}
public Connection getConnection() {
return connection;
}
public void setConnection(Connection connection) {
this.connection = connection;
}
public Statement getStatement() {
return statement;
}
public void setStatement(Statement statement) {
this.statement = statement;
}
public ResultSet getResultset() {
return resultset;
}
public void setResultset(ResultSet resultset) {
this.resultset = resultset;
}
}
package tong.day5_2.facade;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 打印输出ResultSet结果集
* @author tong
*
*/
public class PrintResult {
public void printResultSet(ResultSet resultset) {
try {
if (resultset.next()) {
String username = resultset.getString("username");
String passwd = resultset.getString("passwd");
System.out.println("username:"+username+",password:"+passwd);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package tong.day5_2.facade;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 释放数据库有关所有资源
* @author tong
*
*/
public class ReleaseDB {
//依次关闭数据库资源:resultset、statement、connection
public void close(Connection connection,Statement statement,ResultSet resultset) {
try {
if (resultset!=null) {
resultset.close();
}
if (statement!=null) {
statement.close();
}
if (connection!=null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2、抽象外观类
package tong.day5_2.facade;
//抽象外观类,为外界系统提供一个统一的接口,简化外界系统的调用
public interface Facade {
public abstract void dbOperation(String querySql);
}
3、具体外观类
package tong.day5_2.facade;
import java.sql.ResultSet;
/**
* 执行数据库查询操作的具体外观类,主要负责执行select查询语句,并打印结果集
* @author tong
*
*/
public class DBSelectFacade implements Facade{
private ConfitgInfo confitgInfo;
private DBConnection dbConnection;
private PrintResult printResult;
private ReleaseDB releaseDB;
public DBSelectFacade(){
confitgInfo = new ConfitgInfo();
try {
//获取数据库连接和statement
dbConnection = new DBConnection();
} catch (Exception e) {
e.printStackTrace();
}
printResult = new PrintResult();
releaseDB = new ReleaseDB();
}
//调用其它类的业务方法,提供给客户端一个最简洁的接口
public void dbOperation(String querySql){
//加载数据库配置文件初始化数据库配置信息
confitgInfo.setConfig();
//查询数据结果
ResultSet resultSet = null;;
try {
resultSet = dbConnection.select(querySql);
} catch (Exception e) {
e.printStackTrace();
}
//输出数据结果集
printResult.printResultSet(resultSet);
//释放数据库的所有资源
releaseDB.close(dbConnection.getConnection(), dbConnection.getStatement(), dbConnection.getResultset());
}
}
package tong.day5_2.facade;
import java.sql.ResultSet;
/**
* 执行数据库更新操作的具体外观类,主要负责执行INSERT,DELETE,UPDATE更新语句
* @author tong
*
*/
public class DBUpdateFacade implements Facade{
private ConfitgInfo confitgInfo;
private DBConnection dbConnection;
private ReleaseDB releaseDB;
public DBUpdateFacade(){
confitgInfo = new ConfitgInfo();
try {
//获取数据库连接和statement
dbConnection = new DBConnection();
} catch (Exception e) {
e.printStackTrace();
}
releaseDB = new ReleaseDB();
}
//调用其它类的业务方法,提供给客户端一个最简洁的接口
public void dbOperation(String querySql){
//加载数据库配置文件初始化数据库配置信息
confitgInfo.setConfig();
//执行INSERT ,DELETE,UPDATE 更新语句
try {
dbConnection.update(querySql);
} catch (Exception e) {
e.printStackTrace();
}
//释放数据库的所有资源
releaseDB.close(dbConnection.getConnection(), dbConnection.getStatement(), dbConnection.getResultset());
}
}
4、客户端调用
package tong.day5_2.facade;
/**
* 客户端测试类只要调用外观模式类,就可以简单操作数据库,外观设计模式对用户屏蔽了数据库的一系列操作。
* 外观模式最大的特点将细粒度的对象包装成粗粒度的对象,应用程序通过访问这个外观对象,来完成细粒度对象的调用。
* 我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性
* @author tong
*
*/
public class FacadeTest {
/**
* @param args
*/
public static void main(String[] args) {
String sqlString = "select username,password from user";
String updateString = "update user set username='zhangsan' where username='lisi'";
DBSelectFacade dBuseFacade = null;;
DBUpdateFacade dbUpdateFacade = null;
try {
//调用查询数据库的外观类对象来查询数据
dBuseFacade = new DBSelectFacade();
dBuseFacade.dbOperation(sqlString);
//调用更新数据库的外观类对象来更新数据
dbUpdateFacade = new DBUpdateFacade();
dbUpdateFacade.dbOperation(updateString);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
四、初始化数据库所需的Config.properties配置文件
jdbcDriver=oracle.jdbc.driver.OracleDriver
jdbcUrl=jdbc:oracle:thin:@192.168.1.230:1521:orcl
DatabaseUser=system
DatabasePassword=tiger