适配器模式与Liskov替换

时间:2011-02-25 15:00:48

标签: design-patterns adapter solid-principles liskov-substitution-principle

适配器设计模式用于将类(Target)的接口转换为客户期望的另一个接口(Adaptee)。适配器允许不兼容的类一起工作,否则因为它们的接口不兼容而无法使用。

适配器模式可以通过两种方式实现:继承(适配器模式的类版本)和Composition(适配器模式的对象版本)。

我的问题是关于使用继承实现的适配器模式的类版本。

以下是绘图编辑器的示例:

Figure 1:

interface Shape   
{   
        Rectangle BoundingBox();   

        Manipulator CreateManipulator();   
}   

class TextView   
{   
        public TextView() { }   

        public Point GetOrigin() { }   

        public int GetWidth() { }   

        public int GetHeight() { }   
}  
interface Shape
{
        Rectangle BoundingBox();

        Manipulator CreateManipulator();
}

class TextView
{
        public TextView() { }

        public Point GetOrigin() { }

        public int GetWidth() { }

        public int GetHeight() { }
}

我们希望重用TextView类来实现TextShape,但是接口是不同的,因此,TextView和Shape对象不能互换使用。

是否应该更改TextView类以符合形状界面?也许不是。

TextShape可以通过以下两种方式之一调整TextView界面到形状的界面:

  1. 继承Shape的接口和TextView的实现(适配器模式的类版本)
  2. 通过在TextShape对象中编写TextView实例并使用TextView实例(适配器模式的对象版本)实现TextShape的接口。
  3. 类适配器

    Figure 2:

    interface Shape   
    {   
        Rectangle BoundingBox();   
    
        Manipulator CreateManipulator();   
    }   
    
    class TextView   
    {   
        public TextView() { }   
    
        public Point GetOrigin() { }   
    
        public int GetWidth() { }   
    
        public int GetHeight() { }   
    }   
    
    class TextShape : TextView, Shape   
    {   
        public Rectangle BoundingBox()   
        {   
            Rectangle rectangle;   
            int x, y;   
            Point p = GetOrigin();   
            x = GetWidth();   
            y = GetHeight();   
    
            //...   
    
            return rectangle;   
        }  
    
        #region Shape Members   
    
        public Rectangle Shape.BoundingBox()   
        {   
            return new TextBoundingBox();   
        }   
    
        public Manipulator Shape.CreateManipulator()   
        {   
            return new TextManipulator();   
        }  
    
        #endregion   
    }  
    

    现在提问:-)。 TextShape继承自Shape,特别是从TextView继承有效的“是一种”关系吗?如果没有,它是否违反了Liskov's Substitution Principle

1 个答案:

答案 0 :(得分:4)

它不违反Liskov替换原则,除非你在子类中有某些东西使它的行为方式对超类没有意义(违反了超类的契约)。这当然是不完整的代码,但我没有看到任何迹象。

它可能违反Single Responsibility Principle,但我不确定这是适配器实现中的一个巨大问题。

我通常更喜欢代表方式。