一、模式简介
外观模式(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); } }