适配器和外观模式

1、   基本概述ide

1:现实中存在三角插头适配成双插头,等其余各类形式的适配器来链接不兼容的两个物体。同理在代码中也存在适配器模式来兼容两个不一样的代码接口。性能

2:KTV包间打开一个启动开关,就打开party模式(音响、屏幕、灯光、换气、点歌台等),一个简单的开关来控制其余更多的任务。同理在代码中也存在外观模式来简化子系统(更多任务)的功能。测试

2、详细说明this

1.适配器模式:将一个类的接口、转换成客户指望的另外一个接口,适配器让本来接口不兼容的类能够合做无间编码

这个适配器模式充满良好的OO设计原则,使用对象组合,以修改的接口包装被适配者,这种作法还有额外的优势,那就是被适配者的任何子类,均可以搭配着适配器使用。spa

 

 

问:一个适配器须要作多少“适配”工做?若是我须要实现一个很大的目标接口,彷佛有“不少”工做要作。设计

答:实现一个适配器所须要进行的工做,的确和目标接口的大小成正比。若是不用适配器,你就必须改写客户端的代码来调用这个新的接口,将会花许多力气来作大量的调查工做和代码改写工做。相比之下,提供一个适配器类,将全部的改变封装在一个类中,是比较好的作法。code

问:一个适配器只可以封装一个类吗?对象

答:适配器模式的工做是将一个接口转换成另外一个。虽然大多数的适配器模式所采起的例子都是让一个适配器包装一个适配器者,但咱们都知道这个世界其实复杂多了,因此你可能絮叨一些情况,须要让一个适配器包装多个被被适配者。这涉及另外一个模式,被称为外观模式,人们经常将外观模式和适配器模式混为一谈。blog

问:万一个人系统中新旧并存,旧的部分指望旧的厂商接口,但咱们却已经使用新厂商的接口编写了这一部分。

答:能够建立一个双向的适配器,支持两边的接口。想建立一个双向的适配器,就必须实现所涉及的两个接口,这样这个适配器能够当作旧的接口、新的接口使用。

 

其实适配器模式有两种形式,对象适配器(在上面进行了说明)、和类适配器,类适配器须要用到多重继承(在C#中是不可能的)。

 

2.外观模式:提供了一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层接口,让子系统更容易使用。

下图为外观模式的示意图

 

假若有一个家庭影院,在咱们观赏电影时,必须先执行一些任务(普通方式)。

(1)  打开爆米花机

(2)  开始爆米花机

(3)  将灯光调暗

(4)  放下屏幕

(5)  打开投影机

(6)  ...

(7)  省略更多步骤

(8)  开始播放

面对以上中状况,可使用外观来简化接口。以下图

 

 

问:若是外观封装了子系统的类,那么须要底层功能的客户如何接触这些了类?

答:外观没有“封装”子系统的类,外观只提供简化的接口。因此客户若是以为有必要,依然能够直接使用子系统的类。这是外观模式一个很好的特征,提供简化的接口的同时,依然将系统完整的功能暴露出来,以供须要的人使用。

问:每一个子系统只能有一个外观吗?

答:不,你能够为一个子系统建立许多个外观。

问:可不能够这样说,适配器模式和外观模式之间的差别在于,适配器包装一个类,而外观能够表明许多类?

答:不对!适配器模式将一个或多个类接口变成客户所指望的一个接口。虽然大多数教科书所采用的例子中适配器只适配一个类,可是你能够适配许多类来提供一个接口让客户编码。相似的,一个外观也能够只针对一个拥有复杂接口的类提供简化的接口。两种模式的差别,不在于它们“包装”了几个类,而是在于它们的意图。(可在总结中查看)

 

3.设计原则:最少知识原则:只和你的密友谈话。

    最少知识原则告诉咱们要减小对象之间的交互,只留下几个“密友”。这个原则但愿咱们在设计中,不要让太多的类耦合在一块儿,省得修改系统中一部分,会影响到其余部分。若是许多类之间相互依赖,那么这个系统就会变成一个易碎的系统,它须要花许多成本维护,也会由于太复杂而不容易被其余人了解。

    如何不要赢得太多的朋友和影响太多的对象。

    这个原则提供了一些方针:就职何对象而言,在该对象的方法内,咱们只应该调用属于如下范围的方法:

(1)  该对象自己;

(2)  被当作方法的参数而传递进来的对象;

(3)  此方法所建立或实例化的任何对象;

(4)  对象的任何组件(把组件想象成是被实例化的变量所引用的任何对象);

 

 

问:还有另外一个原则,叫作得墨忒耳法则(Law of Demeter),它和最少知识原则有什么关系?

答:其实两个名词指的是同一个原则,咱们倾向于使用最少知识原则来称呼它是由于如下两个缘由。

(1)  这个名字更直接。

(2)  法则(Law)给人的感受是强制的。事实上,没有任何原则是法律,全部的原则都应该在有帮助的时候才遵照。

全部的设计都难免须要折衷(在抽象和速度之间取舍,在空间和时间之间平衡...)。虽然原则提供了方针,但在采用以前,必须全盘考虑全部的因素。

问:采用最少知识原则有什么缺点吗?

答:虽然这个原则减小了对象之间的依赖,研究显示这会减小软件的维护成本;可是采用这个原则也会致使更多的“包装”类被制造出来,以处理和其余组件的沟通,这可能会致使复杂度和开发时间的增长,并下降运行时的性能。

 

4.总结:

对比三种模式的意图:

装饰者:不改变接口,但加入责任(将一个对象包装起来以增长新的行为和责任)。

适配器:将一个接口转成另外一个接口(将一个对象包装起来以改变其接口)。

外观:让接口更简单(将一群对象“包装”起来以简化其接口)。

 

3、代码列表

 

//适配器模式相关测试类
public interface Iterator<T>
{
    bool HasNext();
    T Next();
    void Remove();
}
public class EnumerationIterator<T> : Iterator<T>
{
    private IEnumerator<T> enumerator;

    public EnumerationIterator(IEnumerable<T> enumerable)
    {
        this.enumerator = enumerable.GetEnumerator();
    }

    public bool HasNext()
    {
        return enumerator.MoveNext();
    }

    public T Next()
    {
        return enumerator.Current;
    }

    public void Remove()
    {
        throw new NotSupportedException();
    }
}
//外观模式的相关测试类
public class Amplifier
{
    public void On()
    {
        Console.WriteLine("Top-0-Line Amplifier on");
    }

    public void SetDvd(DvdPlayer dvd)
    {
        Console.WriteLine("Top-0-Line Amplifier setting DVD player to Top-0-Line DVD Player");
    }

    public void SetVolume(int i)
    {
        Console.WriteLine("Top-0-Line Amplifier surround sound on (5 seakers, 1 subwoofer)");
        Console.WriteLine("Top-0-Line Amplifier setting volume to 5");
    }

    public void Off()
    {
        Console.WriteLine("Top-0-Line Ampliier off");
    }
}
public class CdPlayer
{
    
}
public class Doors
{
    public void Lock()
    {

    }
}
public class DvdPlayer
{
    private string movie;
    public void On()
    {
        Console.WriteLine("Top-0-Line DVD Player on");
    }

    public void Play(string movie)
    {
        this.movie = movie;
        Console.WriteLine("Top-0-Line DVD Player playing \"{0}\"", movie);
    }

    public void Stop()
    {
        Console.WriteLine("Top-0-Line DVD Player stopped \"{0}\"", movie);
    }

    public void Eject()
    {
        Console.WriteLine("Top-0-Line DVD Player eject");
    }

    public void Off()
    {
        Console.WriteLine("Top-0-Line DVD Player off");
    }
}
public class Engine
{
    public void Start()
    {
        
    }
}
public class PopcornPopper
{
    public void On()
    {
        Console.WriteLine("Popcorn Popper on");
    }

    public void Pop()
    {
        Console.WriteLine("Popcorn popper popping popcorn!");
    }

    public void Off()
    {
        Console.WriteLine("Popcorn Popper off");
    }
}
public class Projector
{
    public void On()
    {
        Console.WriteLine("Top-0-Line Projector on");
    }

    public void WideScreenMode()
    {
        Console.WriteLine("Top-0-Line Projector in widescreen mode (19*9 aspect ratio)");
    }

    public void Off()
    {
        Console.WriteLine("Top-0-Line Projector off");
    }
}
public class Screen
{
    public void Down()
    {
        Console.WriteLine("Theater Screen going down");
    }

    public void Up()
    {
        Console.WriteLine("Theater Screen going up");
    }
}
public class TheaterLights
{
    public void Dim(int i)
    {
        Console.WriteLine("Theater Ceiling Lights dimming to {0}%", i);
    }

    public void On()
    {
        Console.WriteLine("Theater Ceiling Lights on");
    }
}
public class Tuner
{
    
}
public class HomeTheaterFacade
{
    private Amplifier amp;
    private Tuner tuner;
    private DvdPlayer dvd;
    private CdPlayer cd;
    private Projector projector;
    private TheaterLights lights;
    private Screen screen;
    private PopcornPopper popper;

    public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvd, CdPlayer cd, Projector projector, TheaterLights lights, Screen screen, PopcornPopper popper)
    {
        this.amp = amp;
        this.tuner = tuner;
        this.dvd = dvd;
        this.cd = cd;
        this.projector = projector;
        this.lights = lights;
        this.screen = screen;
        this.popper = popper;
    }

    public void WatchMovie(string movie)
    {
        Console.WriteLine("Get ready to watch a movie...");
        popper.On();
        popper.Pop();
        lights.Dim(10);
        screen.Down();
        projector.On();
        projector.WideScreenMode();
        amp.On();
        amp.SetDvd(dvd);
        amp.SetVolume(5);
        dvd.On();
        dvd.Play(movie);
    }

    public void EndMovie()
    {
        Console.WriteLine("Shutting movie theathe down...");
        popper.Off();
        lights.On();
        screen.Up();
        projector.Off();
        amp.Off();
        dvd.Stop();
        dvd.Eject();
        dvd.Off();
    }
}
//执行测试
[Test]
public void HomeTheaterTestDrive()
{
    Amplifier amp = new Amplifier();
    Tuner tuner = new Tuner();
    DvdPlayer dvd = new DvdPlayer();
    CdPlayer cd = new CdPlayer();
    Projector projector = new Projector();
    Screen screen = new Screen();
    TheaterLights lights = new TheaterLights();
    PopcornPopper popper = new PopcornPopper();
    HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, lights, screen, popper);
    homeTheater.WatchMovie("Raiders of the lost ark");
    homeTheater.EndMovie();
}
View Code

 

------------------------以上内容根据《Head First Design Mode》进行整理

相关文章
相关标签/搜索