[学习笔记]设计模式[6]-{适配器模式&外观模式}

时间:2022-10-09 22:01:26

设计原则

最少知识原则:只和你的密友谈话

这个原则的意思是,在系统设计的过程中,不要让太多的类耦合在一起,免得对系统一部分的修改会影响到其他部分。在设计系统之前,应该首先注意对象与对象之间的交互关系,尽量减少一个类说依赖的类的数量。

设计模式

这一章有两个设计模式,适配器模式可以将一个接口转为另一个接口,外观模式的意图是让接口更加简单

适配器模式

适配器的定义如下:
适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
适配器模式简单的说来就是用类C继承类A,在实现类A的方法的时候调用类B的方法。
简单的模式如下:
A类是需要适配的对象(例如两相插头):

public class A {
    public void funcA1(){
        //类A做的事情
    }
    public String funcA2(){
        //类A做的另一件事
    }
}

B类是需要被适配的对象(例如三相插孔):

public class B{
    public void funcB1(){
        //类B做的事情
    }
    public String funcA2(){
        //类B做的另一件事
    }
}

如果想让A类的使用者可以使用B类中的方法而不需要对A做修改,就可以使用适配器模式。
下面的类是适配器类C:

public class C extends A{
    B b;
    public C(B b){
        this.b = b;
    }
    public void funcA1(){
        //类A做的事情现在变成了B类做的事情
        b.funcB1();
    }
    public String funcA2(){
        //类A做的另一件事也变成了B类做的事情
        b.funcB2();
    }
}

使用方法如下:

public static void main(String[] args){
    A a = new A();
    A c = new C(new B()); //C继承了A,所以也可以传入ADoThing方法。
    ADoThing(a);
    ADoThing(c);//这时候其实做的是B做的事情。
}
//这个方法是要A去完成它的事情
public static void ADoThing(A a){
    a.funcA1();
    a.funcA2();
}

从上面的例子可以看出来,通过适配器模式可以让我们减少对代码的修改(ADoThing方法不用修改)而获得期望的效果。减少对原有代码的修改就可以保证新增的功能不会对旧的逻辑产生影响。
下面的适配器模式的类图:
[学习笔记]设计模式[6]-{适配器模式&外观模式}

外观模式

还是先把外观模式的定义给出:
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
外观模式可能是最容易理解的一种模式了。就是使用一个类把系统中一些可以组合起来的类组合封装起来,对外的接口只提供一个类。这样就可以满足“最少知识原则”,两个系统之间只有一对需要依赖的类。
下面举一个实际的例子:
你需要组装一个家庭影院的系统,系统中有幕布、投影机、DVD机、音箱等等。。
现在如果你要看一部电影,就不可避免地进行下面一系列的操作:放下幕布、打开DVD机、将DVD插入DVD机、打开投影机、打开音响。。
然后在你看完电影后,你还要进行下面的操作:拉起幕布、将DVD取出、关闭DVD机、关闭投影机、关闭音箱。
是不是很麻烦?
外观模式通过封装这些小系统,可以让你上面的操作变成两个简单的操作完成。下面是代码的实例:
DVD机:

public class DVD{
    public void pushDVD(){
        //插入DVD
    }
    public void popDVD(){
        //弹出DVD
    }
    public void open(){
        //打开DVD机
    }
    public void close(){
        //关闭DVD机
    }
}

幕布:

public class Screen{
    public void down(){
        //放下幕布
    }
    public void up(){
        //收起幕布
    }
}

投影仪:

public class Projector{
    public void on(){
        //打开投影仪
    }
    public void off(){
        //关闭投影仪
    }
}

音箱:

public class Amp{
    public void on(){
        //打开音箱
    }
    public void off(){
        //关闭音箱
    }
}

下面是没有用到外观模式的调用方法:

public static void main(String[] args) {
    DVD dvd = new DVD();
    Screen screen = new Screen();
    Projector projector = new Projector();
    Amp amp = new Amp();
    //准备看电影
    dvd.open();
    dvd.pushDVD();
    screen.down();
    projector.on();
    amp.on();
    //看电影
    //看完电影关闭仪器
    dvd.popDVD();
    dvd.close();
    screen.up();
    projector.off();
    amp.off();
}

可以看出,用户需要依赖很多的类,而且他还需要知道这些类的方法对应的含义。
下面的外观模式可以让用户不需要了解这些小系统所需要的操作,首先定义一个家庭影院的大类,然后把器材都封装到这个大类中。

public class HomeTheater{
    DVD dvd;
    Screen screen;
    Projector projector;
    Amp amp;

    public HomeTheater(DVD dvd, Screen screen, Projector projector, Amp amp){
    this.dvd = dvd;
    this.screen = screen;
    this.projector = projector;
    this.amp = amp;
    }
    //准备看电影
    public void watchMovie(){
    dvd.open();
    dvd.pushDVD();
    screen.down();
    projector.on();
    amp.on();
    }
    //结束看电影
    public void endMovie(){
    dvd.popDVD();
    dvd.close();
    screen.up();
    projector.off();
    amp.off();
    }
}

用户的调用方法就可以简化如下:

public static void main(String[] args) {
    DVD dvd = new DVD();
    Screen screen = new Screen();
    Projector projector = new Projector();
    Amp amp = new Amp();
    HomeTheater homeTheater = new HomeTheater(dvd, screen, projector, amp);
    //准备看电影
    homeTheater.watchMovie();
    //看电影
    //看完电影关闭仪器
    homeTheater.endMovie();
}

现在的用户可以不直接依赖那些小系统,而通过HomeTheater这一个类就可以完成之前的需求。而且用户也不需要知道小系统之间是如何操作的。
最后是外观模式的类图:
[学习笔记]设计模式[6]-{适配器模式&外观模式}