外观模式是什么?
简而言之外观模式就是定义了一个将子系统的一组接口集成在一起的高层接口,一提供一个一致的界面,通过这个界面,其他的系统可以方便的调用子系统的功能。而忽略子系统内部发生的变化。
使用外观模式需要注意的几点:
一个系统有多个外观类
在外观模式中,通常只需要一个外观类,并且此外观类只有一个实例,换言之它是一个单例类。在很多情况下为了节约系统资源,一般将外观类设计为单例类。当然这并不意味着在整个系统里只能有一个外观类,在一个系统中可以设计多个外观类,每个外观类都负责和一些特定的子系统交互,向用户提供相应的业务功能。
不要试图通过外观类为子系统增加新行为
不要通过继承一个外观类在子系统中加入新的行为,这种做法是错误的。外观模式的用意是为子系统提供一个集中化和简化的沟通渠道,而不是向子系统加入新的行为,新的行为的增加应该通过修改原有子系统类或增加新的子系统类来实现,不能通过外观类来实现。
外观模式与迪米特法则
外观模式创造出一个外观对象,将客户端所涉及的属于一个子系统的协作伙伴的数量减到最少,使得客户端与子系统内部的对象的相互作用被外观对象所取代。外观类充当了客户类与子系统类之间的“第三者”,降低了客户类与子系统类之间的耦合度,外观模式就是实现代码重构以便达到“迪米特法则”要求的一个强有力的武器。
抽象外观类的引入
外观模式最大的缺点在于违背了“开闭原则”,当增加新的子系统或者移除子系统时需要修改外观类,可以通过引入抽象外观类在一定程度上解决该问题,客户端针对抽象外观类进行编程。对于新的业务需求,不修改原有外观类,而对应增加一个新的具体外观类,由新的具体外观类来关联新的子系统对象,同时通过修改配置文件来达到不修改源代码并更换外观类的目的。
外观模式方法最适合提供特定的高层次的业务的服务,而不是进行底层次的单独的业务执行。
实例分析
这次我们来关注一下土豪的个人生活,话说土豪下班回到家里后首先要做的就是把灯打开,我们假设他一共需要打开三个灯,然后就是打开热水器烧水准备洗澡,在等待的过程还会打开电视机看新闻。如果我们用一般的方法来实现的话,代码就会是下面这个样子。
package myDesignPatternsTest.InferMode.FacadePatternModel;
/**
* 电灯类
*/
public class Light {
public void open(){
System.out.println("opened Light");
}
}
package myDesignPatternsTest.InferMode.FacadePatternModel;
/**
* 热水器
*/
public class Heater {
public void open(){
System.out.println("opened heater");
}
}
package myDesignPatternsTest.InferMode.FacadePatternModel;
/**
* 电视类
*/
public class Tv {
public void open(){
System.out.println("opened Tv");
}
}
/**
* main 方法要去把三个灯,热水器,电视都打开
*/
public class main {
public static void main(String[] args) {
Light light1=new Light();//一号灯
Light light2=new Light();//二号灯
Light light3=new Light();//三号灯
Heater haierHeater = new Heater();
Tv SUNSANGTV=new Tv();
light1.open();
light2.open();
light3.open();
haierHeater.open();
SUNSANGTV.open();
}
}
既然是土豪,怎么可能让土豪一个一个的去打开开关呢?在这里我们就可以用外观模式了。
package myDesignPatternsTest.InferMode.FacadePatternModel;
/**
* 遥控器
*/
public class Facade {
Light light1=new Light();//一号灯
Light light2=new Light();//二号灯
Light light3=new Light();//三号灯
Heater haierHeater = new Heater();
Tv SUNSANGTV=new Tv();
public void open(){
light1.open();
light2.open();
light3.open();
haierHeater.open();
SUNSANGTV.open();
}
public static void main(String[] args) {
Facade facade=new Facade();
facade.open();
}
}