C#中没有继承的装饰模式。这是正确的吗?

时间:2015-04-22 09:47:42

标签: c# inheritance design-patterns composition

 public interface IMovable
    {
        void Move();
    }

    public interface IUnloadable
    {
        void Unload();
    }

    public class Vehicle : IMovable
    {
        public void Move()
        {
            Console.Write("moving");
        }
    }

    public class Truck : IMovable, IUnloadable
    {
        private Vehicle Veh;

        public Truck(Vehicle veh)
        {
            this.Veh = veh;
        }

        public void Move()
        {
            Veh.Move();
            Console.Write("reverse with beepy noise as well");
        }

        public void Unload()
        {
           Console.Write("Unload");
        }
    }

如果这是装饰模式。装饰者模式和构图之间有什么区别?我已经看到了使用继承的这种模式的例子。例如维基百科上的Java示例。

我根本没有看到使用继承的必要性,或者我错过了什么?

2 个答案:

答案 0 :(得分:8)

根据定义,装饰器模式将实现与其正在装饰的组件相同的接口。想法是客户端代码不需要改变。它可以依赖于之前使用的相同抽象。

例如:

public interface IMovable
{
    void Move();
}

public class Truck : IMovable
{
    public void Move()
    {
        Console.Write("moving");
    }
}

public class NoisyMovable : IMovable //1.Implement same interface
{
    private IMovable movable;
    public NoisyMovable(IMovable movable)//2.Wrap same interface
    {
        this.movable = movable;
    }

    public void Move()
    {
        movable.Move();            
        Console.Write("Make noise");
    }
}

如果你注意到NoisyMovable类,它就是一个装饰器,因为它实现了IMovable抽象并包装了它。

有了这个,您就不必创建许多类,例如NoisyVehicleNoisyTruckNoisyCar等。只需CarTruck够了;您可以使用单个装饰器添加噪音。

IMovable movable = new NoisyMovable(new Truck ());//Noisy Truck
IMovable movable = new NoisyMovable(new Car());//Noisy car
//etc
另一方面,

组合不需要包装它实现的接口的相同实现。它可以实现一个接口并包装任何其他接口。

你的错误是你的Truck类采用Vehicle的实例。它不应该,而应该采用IMovable的任何实例。它应该适用于IMovable

的任何实现

答案 1 :(得分:1)

  

装饰者模式和构图之间有什么区别?

从概念上讲,装饰器修改它包装的(单个)对象的行为,而复合(模式)具有基于它聚合的(多个)对象组合的行为。

  

我根本没有看到使用继承的必要性,或者我错过了什么?

继承很有用,因此您可以拥有多个装饰器并嵌套它们。例如,SelfDriver包裹Truck包裹Vehicle。忽略IUnloadable,第二个装饰者就是 SelfDriver

Class diagram in PlantUML

代码如下所示:

IMovable sd = new SelfDriver(new Truck(new Vehicle())));

对象图如下所示:

Object diagram in PlantUML