HeadFirst设计模式--适配器模式

来源:互联网 发布:excel拆分数据公式 编辑:程序博客网 时间:2024/06/06 08:43

适配器模式

定义:将一个类的接口,转换成客户期望的另一个接口。适配器让原来接口不兼容的类可以合作无间。

某些时刻因为两个类之间接口并不匹配。尤其是在程序进行改进的时候,对原来的功能进行改进。这个时候为了在不改变原来代码的基础上实现性能的提升,我们需要利用这个接口转换回原来的类。如下的代码:

 interface Duck    {        void quack();        void fly();    }    class MallardDuck : Duck    {        public void quack()        {            Console.WriteLine("Quack");        }        public void fly()        {            Console.WriteLine("I'm flying");        }    }    interface Turkey    {        void gobble();        void fly();    }    class WildTurkey : Turkey    {        public void gobble()        {            Console.WriteLine("Gobble gobble");        }        public void fly()        {            Console.WriteLine("I'm flying a short distance");        }    }    class TurkeyAdapter : Duck    {        Turkey turkey;        public TurkeyAdapter(Turkey turkey)        {            this.turkey = turkey;        }        public void quack()        {            turkey.gobble();        }        public void fly()        {            for (int i = 0; i < 5; i++)            {                turkey.fly();            }        }    }    class DuckTestDriver    {        public static void testDuck(Duck duck)        {            duck.quack();            duck.fly();        }        public static void Test()        {            MallardDuck duck = new MallardDuck();            WildTurkey turkey = new WildTurkey();            Duck turkeyAdapter = new TurkeyAdapter(turkey);//强制类型转换            Console.WriteLine("The Turkey says...");            turkey.gobble();            turkey.fly();            Console.WriteLine("\n The Duck says...");            testDuck(duck);            Console.WriteLine("\n The TurkeyAdapter says...");            testDuck(turkeyAdapter);        }    }

    此段代码中包含一个鸭子类以及一个火鸡类,因为鸭子不够,我们希望使用火鸡来代替,但是火鸡并不能叫,于是我们使用一个封装的类,调用火鸡中其它的方法。其UML图为如下所示:

  

 运行结果为:

 

但是新的问题是,一般我们对原来代码的改进,可能会引入新的成员函数,或者拓展新的功能。对了,就是前面所说的装饰者模式。这两种模式的侧重点不一样。

装饰者模式:功能的拓展

适配器模式:屏蔽掉类之间的差异

 

2、外观模式(Facade-Patten)

   可以想象这样的一个场景,如果你在家里要看电影,你是不是要进行很多的操作,比如你要关灯之类的,打开投影仪之类的。如果要熟知每一个类,并且知道类里面的方法,显然这种可操作性对于用户来说是不够强的。外观模式就是将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。这就简化用户的操作。

namespace Adapter{    class Amplifier    {        public void on() { }        public void setDvd(DvdPlayer dvd) { }        public void setSurroundSound() { }        public void setVolume(int calue) { }        public void off() { }    }    class Tuner { }    class DvdPlayer    {        public void on() { }        public void play(String strDes) { }        public void off() { }        public void stop() { }        public void eject() { }    }    class CdPlayer { }    class Projector    {        public void on() { }        public void wideScreenMode() { }        public void off() { }    }    class TheaterLights    {        public void dim(int n) { }        public void on() { }    }    class Screen    {        public void up() { }    }    class PopcornPopper    {        public void on() { }        public void pop() { }        public void off() { }    }    //构造家庭影院的外观    class HomeTheaterFacade    {        Amplifier amp;        Tuner tuner;        DvdPlayer dvd;        CdPlayer cd;        Projector projector;        TheaterLights lights;        Screen screen;        PopcornPopper popper;        public HomeTheaterFacade(Amplifier amp, Tuner tun, DvdPlayer dvd, CdPlayer cd, Projector projector, Screen screen,            TheaterLights lights, PopcornPopper popper)        {            this.amp = amp;            this.tuner = tun;            this.dvd = dvd;            this.cd = cd;            this.projector = projector;            this.screen = screen;            this.lights = lights;            this.popper = popper;        }        public void watchMovie(String movie)        {            Console.WriteLine("Get ready to watch a movie...");            popper.on();            popper.pop();            lights.dim(10);            projector.on();            projector.wideScreenMode();            amp.on();            amp.setDvd(dvd);            amp.setSurroundSound();            amp.setVolume(5);            dvd.on();            dvd.play(movie);        }        public void endMovie()        {            Console.WriteLine("Shutting movie theater down...");            popper.off();            lights.on();            screen.up();            projector.off();            amp.off();            dvd.off();            dvd.stop();            dvd.eject();            dvd.off();        }        public void test()        {            HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, screen, lights, popper);            homeTheater.watchMovie("Raiders of the lost ark");            homeTheater.endMovie();        }    }    //下面的例子为遵循最少知识的原则。    class Engine    {        public void start() { }    }    class Key    {        public bool turns()        {            return true;        }    }    class Doors    {        public void lockDoor() { }    }    class Car    {        Engine engine;        public Car() { }        public void start(Key key)        {            Doors doors = new Doors();            Boolean authorized = key.turns();            if (authorized)            {                engine.start();//利用对象组建                updateDashboardDisplay();                doors.lockDoor();//利用创建的对象或者实例            }        }        public void updateDashboardDisplay()        {        }    }}//对于外观模式其实就是封装具体的操作内容,简化用户的行为,要求不与太多的对象进行交流,也就是尽量保持类中其它对象的数目
           Amplifier amp = new Amplifier();            Tuner tuner=new Tuner ();            DvdPlayer dvd=new DvdPlayer ();            CdPlayer cd=new CdPlayer ();            Projector projector=new Projector ();            TheaterLights lights=new TheaterLights ();            Screen screen=new Screen ();            PopcornPopper popper=new PopcornPopper ();            HomeTheaterFacade homeThreater = new HomeTheaterFacade(amp,tuner,dvd,cd,projector,screen,lights,popper);            homeThreater.test();
其UML图为:




适配器与外观模式之间的差异。

外观:不仅简化了接口,也将客户从组建的子系统中解耦。

适配器:主要的意图是将接口转换成不同的接口。

   在外观模式中利用到“最少知识”的原则。也就是只和你的密友谈话。从Car类中我们看到是直接的调用类中的方法,而非层层调用的关系。这就在一定程度上解耦了。它也就是有名的迪米特法则(Law of Demeter),其英文的解释是:talk only toyour immediate friends外观通过将子系统组合进来,将工作委托给子系统执行,使得客户从复杂的子系统中解耦。



0 0
原创粉丝点击