设计模式-门面(译)

153 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

门面模式是一种结构设计模式(structural design patterns)(适配器模式和装饰器模式也是结构设计模式)。门面模式可以更容易的帮助客户程序和一个系统进行交互

门面模式

为一个子系统的一系列接口提供一个统一的接口。

门面模式提供了一个更高阶的接口可以让子系统更加易用。假设我们有一应用有一系列的接口来使用Mysql/Oracle数据库,并且可以生产不同类型的报表,比如html或者pdf报表,因此我们需要使用不同接口集合来操作不同类型的数据库。

现在一个客户端程序可以使用这些接口老获取必要的数据库连接来生成报表。但是当复杂度变高或者接口行为名字混淆时,客户端程序将会很难使用它。

所以我们可以应用门面模式来在上层提供一个包装的接口来帮助客户端程序使用。

接口集合

我们有两个帮助类接口,MySqlHelper 和 OracleHelper

package com.journaldev.design.facade;

import java.sql.Connection;

public class MySqlHelper {
	
	public static Connection getMySqlDBConnection(){
		//get MySql DB connection using connection parameters
		return null;
	}
	
	public void generateMySqlPDFReport(String tableName, Connection con){
		//get data from table and generate pdf report
	}
	
	public void generateMySqlHTMLReport(String tableName, Connection con){
		//get data from table and generate pdf report
	}
}
package com.journaldev.design.facade;

import java.sql.Connection;

public class OracleHelper {

	public static Connection getOracleDBConnection(){
		//get Oracle DB connection using connection parameters
		return null;
	}
	
	public void generateOraclePDFReport(String tableName, Connection con){
		//get data from table and generate pdf report
	}
	
	public void generateOracleHTMLReport(String tableName, Connection con){
		//get data from table and generate pdf report
	}
	
}

门面模式接口

package com.journaldev.design.facade;

import java.sql.Connection;

public class HelperFacade {

	public static void generateReport(DBTypes dbType, ReportTypes reportType, String tableName){
		Connection con = null;
		switch (dbType){
		case MYSQL: 
			con = MySqlHelper.getMySqlDBConnection();
			MySqlHelper mySqlHelper = new MySqlHelper();
			switch(reportType){
			case HTML:
				mySqlHelper.generateMySqlHTMLReport(tableName, con);
				break;
			case PDF:
				mySqlHelper.generateMySqlPDFReport(tableName, con);
				break;
			}
			break;
		case ORACLE: 
			con = OracleHelper.getOracleDBConnection();
			OracleHelper oracleHelper = new OracleHelper();
			switch(reportType){
			case HTML:
				oracleHelper.generateOracleHTMLReport(tableName, con);
				break;
			case PDF:
				oracleHelper.generateOraclePDFReport(tableName, con);
				break;
			}
			break;
		}
		
	}
	
	public static enum DBTypes{
		MYSQL,ORACLE;
	}
	
	public static enum ReportTypes{
		HTML,PDF;
	}
}

客户程序

让我们看看在不使用门面模式和使用门面模式时的的客户端代码

package com.journaldev.design.test;

import java.sql.Connection;

import com.journaldev.design.facade.HelperFacade;
import com.journaldev.design.facade.MySqlHelper;
import com.journaldev.design.facade.OracleHelper;

public class FacadePatternTest {

	public static void main(String[] args) {
		String tableName="Employee";
		
		//generating MySql HTML report and Oracle PDF report without using Facade
		Connection con = MySqlHelper.getMySqlDBConnection();
		MySqlHelper mySqlHelper = new MySqlHelper();
		mySqlHelper.generateMySqlHTMLReport(tableName, con);
		
		Connection con1 = OracleHelper.getOracleDBConnection();
		OracleHelper oracleHelper = new OracleHelper();
		oracleHelper.generateOraclePDFReport(tableName, con1);
		
		//generating MySql HTML report and Oracle PDF report using Facade
		HelperFacade.generateReport(HelperFacade.DBTypes.MYSQL, HelperFacade.ReportTypes.HTML, tableName);
		HelperFacade.generateReport(HelperFacade.DBTypes.ORACLE, HelperFacade.ReportTypes.PDF, tableName);
	}

}

可以看到使用门面模式时,客户段代码变得简单而且干净,避免了在客户端有过多的逻辑。jdbc driver manager类获取数据看连接就是一个很好的门面模式的例子

重要点

  • 门面模式对客户端而言很像一个帮助类,它并没有隐藏子系统的接口。是否使用门面模式完全取决于客户端代码
  • 门面模式可以用在开发中的各个地方,通常用在有很多新增的接口是的系统变得复杂
  • 子系统接口不织入门面接口,子系统接口不应该有引用门面接口
  • 门面模式应该被应用在有一系列相似接口时,门面模式的目的是提供一个单一的接口,而不是提供多个接口来做相似的工作
  • 我们可以使用门面模式来提供一个更好的接口给客户端程序

上面就是门面模式,请继续关注更多的设计模式文章

原文链接