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示例。
我根本没有看到使用继承的必要性,或者我错过了什么?
答案 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
抽象并包装了它。
有了这个,您就不必创建许多类,例如NoisyVehicle
,NoisyTruck
,NoisyCar
等。只需Car
,Truck
够了;您可以使用单个装饰器添加噪音。
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
:
代码如下所示:
IMovable sd = new SelfDriver(new Truck(new Vehicle())));
对象图如下所示: