一、模式简介
外观模式(Facade Pattern)可以将一系列复杂的类包装成一个简单的封闭接口。也称门面模式.
二、模式意图
facade(门面)模式的作用在于降低客户端操作与Server之间的耦合度,提供统一的访问
入口供客户端使用。减少回底层变化给客户端使用带来的不便。
它适用于一组相对固定且有实际意义的操作,如去医院看病分为挂号、门诊、划价、化验、
收费、取药等。这些操作都可以由Facade来处理,病人只需要与Facade交互就可以了。
在Facade中,我们实现的只是一种事务处理的抽象,并不涉及具体的事务处理逻辑。比如
挂号,我们只需要告诉Facade我们需要挂号,Facade再去联系具体实现挂号的护士,由
护士最终实现具体挂号操作。
三、模式UML(下图转自http://www.dofactory.com/)
四、模式参与者
门面(Facade)角色:客户端可以调用这个角色的方法。
此角色知晓相关的(一个或者多个)子系统的功能和责任。
在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
子系统(SubSystem)角色:可以同时有一个或者多个子系统。
实现子系统的功能,处理由Facade对象指派的任务。
每一个子系统都不是一个单独的类,而是一个类的集合。
每一个子系统都可以被客户端直接调用,或者被门面角色调用。
子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
五、示例代码
1.子系统代码
public class Account {
String firstName;
String lastName;
final String ACCOUNT_DATA_FILE = "AccountData.txt";
public Account(String fname, String lname) {
firstName = fname;
lastName = lname;
}
public boolean isValid() {
/*
Let's go with simpler validation
here to keep the example simpler.
*/
return false;
}
public boolean save() {
String dataLine = getLastName() + "," + getFirstName();
try {
FileUtils.writeStringToFile(new File(ACCOUNT_DATA_FILE), dataLine);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
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 isValid() {
/*
The address validation algorithm
could be complex in real-world
applications.
Let's go with simpler validation
here to keep the example simpler.
*/
if (getState().trim().length() < 2)
return false;
return true;
}
public boolean save() {
String dataLine = getAddress() + "," + getCity() + "," +
getState();
try {
FileUtils.writeStringToFile(new File(ADDRESS_DATA_FILE), dataLine);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
public String getAddress() {
return address;
}
public String getCity() {
return city;
}
public String getState() {
return state;
}
}
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 isValid() {
/*
Let's go with simpler validation
here to keep the example simpler.
*/
if (getCardType().equals(AccountManager.VISA)) {
return (getCardNumber().trim().length() == 16);
}
if (getCardType().equals(AccountManager.DISCOVER)) {
return (getCardNumber().trim().length() == 15);
}
if (getCardType().equals(AccountManager.MASTER)) {
return (getCardNumber().trim().length() == 16);
}
return false;
}
public boolean save() {
String dataLine =
getCardType() + "," + getCardNumber() + "," +
getCardExpDate();
try {
FileUtils.writeStringToFile(new File(CC_DATA_FILE), dataLine);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
public String getCardType() {
return cardType;
}
public String getCardNumber() {
return cardNumber;
}
public String getCardExpDate() {
return cardExpDate;
}
}
2.Facade代码
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 inAddress) {
address = inAddress;
}
public void setCity(String inCity) {
city = inCity;
}
public void setState(String inState) {
state = inState;
}
public void setFName(String inFName) {
fname = inFName;
}
public void setLName(String inLName) {
lname = inLName;
}
public void setCardType(String inCardType) {
cardType = inCardType;
}
public void setCardNumber(String inCardNumber) {
cardNumber = inCardNumber;
}
public void setCardExpDate(String inCardExpDate) {
cardExpDate = inCardExpDate;
}
public boolean saveCustomerData() {
Address objAddress;
Account objAccount;
CreditCard objCreditCard;
/*
client is transparent from the following
set of subsystem related operations.
*/
boolean validData = true;
String errorMessage = "";
objAccount = new Account(fname, lname);
if (objAccount.isValid() == false) {
validData = false;
errorMessage = "Invalid FirstName/LastName";
}
objAddress = new Address(address, city, state);
if (objAddress.isValid() == false) {
validData = false;
errorMessage = "Invalid Address/City/State";
}
objCreditCard = new CreditCard(cardType, cardNumber,
cardExpDate);
if (objCreditCard.isValid() == false) {
validData = false;
errorMessage = "Invalid CreditCard Info";
}
if (!validData) {
System.out.println(errorMessage);
return false;
}
if (objAddress.save() && objAccount.save() && objCreditCard.save()) {
return true;
} else {
return false;
}
}
}
3.客户端代码
public class AccountManager extends JFrame {
public static final String VISA = "VISA";
public static final String MASTER = "MASTER";
public static final String DISCOVER = "DISCOVER";
public static final String newline = "\n";
public static final String VALIDATE_SAVE = "Validate & Save";
private JComboBox cmbCardType;
private JTextField txtFirstName = new JTextField();
private JTextField txtLastName = new JTextField();
private JTextField txtAddress = new JTextField();
private JTextField txtCity = new JTextField();
private JTextField txtState = new JTextField();
private JTextField txtCardNumber = new JTextField();
private JTextField txtDate = new JTextField();
private JButton submit = new JButton("submit");
private CustomerFacade customer;
public AccountManager() {
super(" Facade Pattern - Example ");
cmbCardType = new JComboBox();
cmbCardType.addItem(AccountManager.VISA);
cmbCardType.addItem(AccountManager.MASTER);
cmbCardType.addItem(AccountManager.DISCOVER);
submit.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
customer = new CustomerFacade();
if(txtFirstName.getText() != null || txtFirstName.getText() != ""){
customer.setFName(txtFirstName.getText());
}
{
//赋值操作
}
customer.saveCustomerData();
}
});
GridLayout layout = new GridLayout(9,2);
setLayout(layout);
add(new JLabel("txtFirstName"));
add(txtFirstName);
add(new JLabel("txtLastName"));
add(txtLastName);
add(new JLabel("txtAddress"));
add(txtAddress);
add(new JLabel("txtCity"));
add(txtCity);
add(new JLabel("cmbCardType"));
add(cmbCardType);
add(new JLabel("txtCardNumber"));
add(txtCardNumber);
add(new JLabel("txtDate"));
add(txtDate);
add(new JLabel());
add(submit);
}
public static void main(String[]args){
JFrame f = new AccountManager();
f.setBounds(100, 100, 600, 800);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}