什么是外观模式(Facade Pattern)呢?
- 外观模式定义了一个将子系统的一组接口集成在一起的高层接口,以提供一个一致的界面。通过这个界面,其他系统可以方便地调用子系统中的功能,而忽略系统内部发生的变化。
使用场景
- 为一个比较复杂的子系统提供一个简单的接口。
- 将客户程序与子系统的实现部分分离,提高子系统的而独立性和可移植性。
- 简化子系统间的依赖关系。
外观模式涉及到子系统的一些类。所谓子系统,是为提供一系列相关的特征(功能)而紧密关联的一组类。例如:一个Account类、Address类和CreditCard类相互关联,成为子系统的一部分,提供在线客户的特征。在真实的应用系统中,一个子系统可能由很多类组成,子系统的客户为了他们的需要,需要和子系统中一些类进行交互,客户和子系统的类进行直接的交互会导致客户端对象和子系统直接高度耦合。任何的类似于对子系统中类的接口的修改,会对依赖于它的所有的客户类造成影响。
对于外观模式而已,就很适用于上述的情况。
外观模式主要是为子系统提供一个更高层次、更简单的接口,从而降低了子系统的复杂度和依赖。这使得子系统更易于使用和管理。外观是一个能为子系统和客户提供简单接口的类。当正确的应用外观,客户不再直接和子系统中的类交互,而是与外观交互。外观承担子系统中类交互的责任。实际上,外观是子系统与客户的接口,这样子外观模式降低了子系统和客户的耦合度。
举个例子:
我们建立一个应用
- 接受客户的详细资料(账户、地址、信用信息)
- 验证输入的信息
- 保存输入的信息到相应的文件中
这三个类分别是 Account、Address和CreditCard,每一个类都有自己的验证和保存数据的方法。
Account.class
public class Account {
String firstName;
String lastName;
final String ACCOUNT_DATA_FILE = "AccountData.txt";
public Account (String fname, String lname){
firstName = fname;
lastNmae = lname;
}
public boolean save(){
FileUtil futil = new FileUtil();
String dataLine = getLastName() + "," + getFirstName();
return futil.writeToFile(ACCOUNT_Data_FILE, dataLine, true, true); //保存
}
public String getFirstName(){
return firstName();
}
public String getLastName(){
return lastName;
}
}
Address.class
public class Address{
String address;
String city;
String state;
final String ADDRESS_DATA_FILE = “Address.txt”;
public Address (String add, String cty, String st){
address = add;
city = cty;
state = st;
}
public boolean save(){
FileUtil futil = new FileUtil();
String dataLine = getAddress() + "," + getCity() + "," + getState();
return futil.writeToFile (ADDRESS_DATA_FILE, dataLine, true, true); //保存
}
public String getAddress(){
return address;
}
public String getCity(){
return city;
}
public String getState(){
return state;
}
}
CreditCard
public class CreditCard [
String cardType;
String cardNumber;
String cardExpDate;
final String CC_DATA_FILE = "CC.txt";
public CreditCard (String ccType, String ccNumber, String ccExpDate){
cardType = ccType;
cardNumber = ccNumber;
cardExpDate = ccExpDate;
}
public boolean save(){
FileUtil futil = new FileUtil();
String dataLine = getCardType() + "," + getCardNumber() + "," + getCardExpDate();
return futil.writeToFile(CC_DATA_FILE, dataLine, true, true);
}
public String getCardType(){
return cardType;
}
public String getCardNumber(){
return cardNumber;
}
public String getCardExpDate(){
return cardExpDate;
}
}
为这三个类提供一个外观接口
CustomerFacade.class
public class CustomerFacade {
private String address;
private String city;
private String state;
private String cardType;
private String cardNumber;
private String cardExpDate;
private String fname;
private String lname;
public void setAddress(String address) {
this.address = address;
}
public void setCity(String city) {
this.city = city;
}
public void setState(String state) {
this.state = state;
}
public void setCardType(String cardType) {
this.cardType = cardType;
}
public void setCardNumber(String cardNumber) {
this.cardNumber = cardNumber;
}
public void setCardExpDate(String cardExpDate) {
this.cardExpDate = cardExpDate;
}
public void setFname(String fname) {
this.fname = fname;
}
public void setLname(String lname) {
this.lname = lname;
}
public boolean saveCustomerData(){
Address address;
Account account;
CreditCard creditCard;
account = new Account(fname, lname);
address = new Address(address, city, state);
creditCard = new CreditCard(cardType, cardNumber, cardExpDate);
account.save();
address.save();
creditCard.save();
}
}
CustomerFacade类以saveCustomData方法的形式提供了业务层次上的服务,客户不是直接跟 子系统的Account、Address和CreditCard三个类直接交互,而是由CustomerFacade对象提供更高层次、更简单的保存数据的操作。
注意事项:
- 在设计外观时,不需要添加额外的功能
- 不要从外观方法中返回子系统中的组件给客户
- 应用外观的目的是提供一个高层次的接口
因此,外观模式最适合提供特定的高层次的业务服务,而不是进行底层单独的业务执行。