装饰器,包装器和适配器图案之间有什么区别



我觉得我一直在使用这些模式系列很多次,但是,对我来说,因为它们的定义 非常相似。基本上,似乎所有这些都是关于包装 的另一个对象或对象扩展或 wrap 它们的行为以及额外的东西。

对于通过存储库模式实现缓存机制的快速示例似乎就是这种情况。这是我可能会从。

开始的快速示例C#代码
public interface IRepository {
  IEnumerable<T> GetItems<T>();
}
public class EntityFrameworkRepository : IRepository {
  ...
}
public class CachedRepository : IRepository {
  private IRepository _repository;
  private ICacheProvider _cache;
  public CachedRepository(IRepository repository, ICacheProvider cache) {
    this._repository = repository;
    this._cache = cache;
  }
  public IEnumerable<T> GetItems<T>() {
    ...
  }
}

例如,这些模式中的哪一种适用于这种情况?谁能简要澄清理论和实践中的差异?

从理论上讲它们是相同的,是intent将一种模式与另一种模式区分开来:

装饰器:

允许对象组合/添加功能,通过将它们与具有相同接口

的类包装。

适配器:

允许您在没有已知接口实现的情况下包装对象 因此,它粘附在接口上。关键是将一个接口"翻译"到另一个接口。

包装器:

从未听说过这是一种设计模式,但我想这只是上述

的通用名称

您指定的示例我将归类为装饰器:cacherepository decorates a IRepository添加缓存功能。

程序员可以编写一个类A类,重点是持有其他类别的对象。类A类。为什么A级包裹在B级上?装饰或适应它。装饰器和适配器是包装纸。


想象A级写作,以便通过调用其B类对象的方法来实现B类的接口。然后,它可以代替B类。除了它使程序员有机会在调用B类对象的方法之前或之后添加一些代码的事实,这是没有其他意义的。此版本A类将称为B类的 Decorator 装饰器在添加一些行为时离开界面相同。

interface ICatInterface {
  public void wakeUp();
}
class Cat implements ICatInterface {
  public void wakeUp() {
    System.out.println("I came. I saw. I napped.");
  }
}
class YogaCat implements ICatInterface {
  private ICatInterface cat;
  public YogaCat(ICatInterface cat) {
    this.cat = cat;
  }
  public void wakeUp() {
    System.out.println("[Stretch]"); // <- This is the decoration.
    cat.wakeUp();
  }
}

请参阅此示例的示例,是一种更复杂的方法,用于在运行时组合不同行为的对象。


想象一下,现在编写了A类以使其实现某些接口C,但主要是通过呼叫对其B类对象的方法实现的。这是将B类可用的方法转换为接口C的一种方法。该类别的A类将称为 ADAPTER 类别的A级。就像您想为手机充电时一样。有一些适配器从墙壁或汽车电源到USB端口。适配器将接口更改为其他接口,但不一定添加任何行为。

interface TakeDirectionsInterface {
  public void turnLeft();
  public void turnRight();
  public void go();
  public void stop();
}
class Driver {
  public enum TurnDirection
  { 
    CLOCKWISE, COUNTERCLOCKWISE;
  }
  public enum FootPedal
  { 
    ACCELERATOR, BRAKE, CLUTCH;
  }
  public void turnSteeringWheel(TurnDirection direction) {
    System.out.println("Turning the steering wheel " + direction.toString() + ".");
  }
  public void pressPedal(FootPedal pedal) {
    System.out.println("Pressing the " + pedal.toString() + "pedal.");
  }
}
class DriverAdapter implements TakeDirectionsInterface {
  private Driver driver;
  public DriverAdapter(Driver driver) {
    this.driver = driver;
  }
  public void turnLeft(){
    driver.turnSteeringWheel(Driver.TurnDirection.COUNTERCLOCKWISE);
  }
  public void turnRight(){
    driver.turnSteeringWheel(Driver.TurnDirection.CLOCKWISE);
  }
  public void go(){
    driver.pressPedal(Driver.FootPedal.ACCELERATOR);
  }
  public void stop(){
    driver.pressPedal(Driver.FootPedal.BRAKE);
  }
}

最新更新