代码Github连接 :https://github.com/tangbi123/Tab-Design-Pattern
Facade
可以为互相关联在一起地错综复杂地类整理出高层接口(API),让系统对外只有一个简单的接口(API),并且考虑系统内部各个类之间地责任关系和依赖关系,按照正确地顺序调用各个类。
示例
文件结构
代码清单
1)Database
public class Database {
private Database(){}
public static Properties getProperties(String dbname){
String filename = dbname + ".txt";
Properties prop = new Properties();
try{
prop.load(new FileInputStream(filename));
}catch (IOException e){
System.out.println("warning:" + filename + "is not found.");
}
return prop;
}
}
mailData.txt
hyuki@hyuki.com=Hiroshi Yuki
hanako@hyuki.com=Hanako Sato
tomura@hyuki.com=Tomura
mamoru@hyuki.com=Mamoru Takahashi
2)HtmlWriter
public class HtmlWriter {
private Writer writer;
public HtmlWriter(Writer writer) {
this.writer = writer;
}
public void title(String title)throws IOException{
writer.write("<html>");
writer.write("<head>");
writer.write("<title>" + title + "</title>");
writer.write("</head>");
writer.write("<body>\n");
writer.write("<h1>" + title + "</h1>\n");
}
public void paragraph(String msg) throws IOException {
writer.write("<p>" + msg + "</p>");
}
public void link(String href, String caption)throws IOException{
paragraph("<a href = \"" + href + "\">"
+ caption + "</a>");
}
public void mailto(String mailaddr, String username)throws IOException{
link("mailto:" + mailaddr, username);
}
public void close() throws IOException{
writer.write("</body>");
writer.write("</html>/n");
writer.close();
}
}
3)PageMaker
public class PageMaker {
private PageMaker(){}
public static void makeWelcomePage(String mailAddr, String filename){
try{
Properties mailProp = Database.getProperties("src/Facade/mailData");
String username = mailProp.getProperty(mailAddr);
HtmlWriter writer = new HtmlWriter(new FileWriter(filename));
writer.title("Welcome to " + username + " 's page!");
writer.paragraph(username + "欢迎来到" + username + " 的主页");
writer.paragraph("等着你的邮件哦");
writer.mailto(mailAddr,username);
writer.close();
System.out.println(filename + "is created for" + mailAddr + "("
+ username + ")");
} catch (IOException e) {
e.printStackTrace();
}
}
}
4)Main
public class FacadeMain {
public static void main(String[] args) {
PageMaker.makeWelcomePage("hyuki@hyuki.com", "welcom.html");
}
}
角色
- Facade(窗口) =》 PageMaker
代表构成系统的许多其他角色的“简单窗口”,向系统外部提供高层接口(API)。
2)构成系统的许多其他角色 =》 Database、HtmlWriter
这些角色各自完成i及的工作,他们并不知道Facade角色;Facade角色调用其他角色进行工作,但是其他角色不会调用Facade角色。
3)Client(请求者)
负责调用Facade角色。
思路要点
Facade角色到底做什么工作
Facade模式可以让复杂的东西看起来简单。
重点是 接口(API)变少了。直接使用一个接口(API)的Facade角色,综合了其他角色的 类和方法、调用顺序。
递归地使用Facade模式
假设现在有几个持有Facade角色类的集合,那么我们可以通过整合这几个集合来引入新的Facade角色 =》 递归地使用Facade。
开发人员不愿意创建Facade角色的原因
Mediator(仲裁者)
当发生麻烦事情的时候,通知仲裁者;当发生设计全体组员的事情时,也通知仲裁者。
当仲裁者下达指示时,组员会立即执行。
团队组员之间不在互相沟通并私自做出决定,而是发生任何事都想仲裁者报告。
仲裁者站在整个团队角度上对组员上报的事情做出决定。
仲裁者成为 Mediator,各组员被称为Colleague。
示例
不让各个对象之间互相通信,而是增加一个仲裁者角色,让哥哥对象之间互相通信,而是增加一个仲裁者角色,让他们各自和仲裁者通信,然后将控制显示的逻辑处理交给仲裁者负责。
代码清单
1)Mediator
public interface Mediator {
public abstract void createColleagues();
public abstract void colleagueChanged();
}
2)Colleague
public interface Colleague {
public abstract void setMediator(Mediator mediator);
public abstract void setColleagueEnabled(boolean enabled);
}
3)ColleagueCheckbox
public class ColleagueCheckbox extends Checkbox implements ItemListener,Colleague {
private Mediator mediator;
public ColleagueCheckbox(String label, CheckboxGroup group, boolean state) throws HeadlessException {
super(label, group, state);
}
@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
@Override
public void setColleagueEnabled(boolean enabled) {
setEnabled(enabled);
}
@Override
public void itemStateChanged(ItemEvent e) {
mediator.colleagueChanged();
}
}
4)ColleagueButton
public class ColleagueButton extends Button implements Colleague {
private Mediator mediator;
public ColleagueButton(String caption){
super(caption);
}
@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
@Override
public void setColleagueEnabled(boolean enabled) {
setEnabled(enabled);
}
}
5)ColleagueTextField
public class ColleagueTextField extends TextField implements TextListener,Colleague {
private Mediator mediator;
public ColleagueTextField(String text, int columns) throws HeadlessException {
super(text, columns);
}
@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
@Override
public void setColleagueEnabled(boolean enabled) {
setEnabled(enabled);
setBackground(enabled? Color.white : Color.lightGray);
}
@Override
public void textValueChanged(TextEvent e) {
mediator.colleagueChanged();
}
}
6)LoginFrame
public class LoginFrame extends Frame implements ActionListener,Mediator {
private ColleagueCheckbox checkGuest;
private ColleagueCheckbox checkLogin;
private ColleagueTextField textUser;
private ColleagueTextField textPass;
private ColleagueButton buttonOk;
private ColleagueButton buttonCancel;
public LoginFrame(String title){
super(title);
setBackground(Color.lightGray);
setLayout(new GridLayout(4,2));
createColleagues();
add(checkGuest);
add(checkLogin);
add(new Label("Username:"));
add(textUser);
add(new Label("Password:"));
add(textPass);
add(buttonOk);
add(buttonCancel);
colleagueChanged();
pack();
show();
}
@Override
public void createColleagues() {
CheckboxGroup g = new CheckboxGroup();
checkGuest = new ColleagueCheckbox("Guest",g,true);
checkLogin = new ColleagueCheckbox("Login",g,false);
textUser = new ColleagueTextField("",10);
textPass = new ColleagueTextField("", 10);
textPass.setEchoChar('*');
buttonOk = new ColleagueButton("OK");
buttonCancel = new ColleagueButton("Cancel");
checkGuest.setMediator(this);
checkLogin.setMediator(this);
textUser.setMediator(this);
textPass.setMediator(this);
buttonOk.setMediator(this);
buttonCancel.setMediator(this);
checkGuest.addItemListener(checkGuest);
checkLogin.addItemListener(checkLogin);
textUser.addTextListener(textUser);
textPass.addTextListener(textPass);
buttonOk.addActionListener(this);
buttonCancel.addActionListener(this);
}
@Override
public void colleagueChanged() {
if(checkGuest.getState()){
textUser.setColleagueEnabled(false);
textPass.setColleagueEnabled(false);
buttonOk.setColleagueEnabled(false);
}
else{
textUser.setColleagueEnabled(true);
userpassChanged();
}
}
private void userpassChanged(){
if(textUser.getText().length() > 0){
textPass.setColleagueEnabled(true);
if(textPass.getText().length() > 0){
buttonOk.setColleagueEnabled(true);
}
else {
buttonOk.setColleagueEnabled(false);
}
}
else{
textPass.setColleagueEnabled(false);
buttonOk.setColleagueEnabled(false);
}
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.toString());
System.exit(0);
}
}
7)Main
public class MediatorMain {
public static void main(String[] args) {
new LoginFrame("Mediator Sample");
}
}
角色
1)Mediator(仲裁者)
负责定义与Colleague角色进行通信和做出决定的接口(API)
2)ConcreteMediator =》 LoginFrame
负责实现Mediator角色的接口,负责实际做出决定
3)Colleague
负责定义与Mediator角色进行通信的接口(API)
4)ConcreteColleague
负责实现Colleague角色的接口api
思路要点
当发生分散灾难
修改 collegueChanged,调试Bug。
这段逻辑分散在 ConcreteColleague中,会难以调试。
通信线路的增加
哪些角色可以复用
ConcreteColleague可以复用,但ConcreteMediator很难服用。