0

According to Wiki https://en.wikipedia.org/wiki/Decorator_pattern#Usage

A decorator makes it possible to add or alter behavior of an interface at run-time. Alternatively, the adapter can be used when the wrapper must respect a particular interface and must support polymorphic behavior, and the Facade when an easier or simpler interface to an underlying object is desired.

I'm not getting it about polymorphic behavior. Where's polymorphic happened in Adaptor, isn't adaptor just transform one interface into another interface ?

WeiChing 林煒清
  • 4,102
  • 2
  • 25
  • 54
  • I think it just means adapter must be an abstraction, so that external client, if complicated enough, can swap between different implementations of adapter. – Binary Baba Aug 11 '18 at 10:49

2 Answers2

2

isn't adaptor just transform one interface into another interface ?

Yes.

Where's polymorphic happened in Adaptor...?

Say you have two classes that do vaguely similar things but have different interfaces. You can wrap one with an adapter so its interface matches the other's interface (or give them both adapters to some shared API), then the same client code can use either one polymorphically.

For example, two similar classes:

struct Car {
    bool start();
    bool accelerate_gently_to(double kph);
};

struct Bicycle {
    bool start();
    bool set_gear(int);
    bool peddle(double rpm);
};

An adapter so one (arbitrarily, the Bicycle) can be controlled using the same interface as the other:

struct Bicycle_Adapter_to_Accelerate_API {
    Bicycle b_;  // member, base, by-pointer - whatever
    bool start() { return b_.start(); }
    bool accelerate_gently_to(double kph) {
        int gear = calculate_best_gear_for_speed(kph);
        if (!b_.set_gear(gear)) return false;
        double rpm = calculate_rpm(kph, wheel_circumference, gear); 
        return b_.peddle(rpm);
    }
};

That allows the client code that treats them polymorphically:

template <typename T>
void control_transport(T& t) {
    t.start();
    t.accelerate_gently_to(20);
    sleep(60);
    t.accelerate_gently_to(25);
}

Say you wanted to use runtime polymorphism (i.e. virtual dispatch) rather than compile time polymorphism: you would have either derived the Car and adapter from a base class with virtual bool start(); and virtual bool accelerate_gently_to(double kph);, or create a second adapter for Car and have both adapters derive from such a base class, then you can dispatch polymorphically from non-templated code:

void control_transport(Transport_Base_Class& t) {
    t.start();
    t.accelerate_gently_to(20);
    sleep(60);
    t.accelerate_gently_to(25);
}
Tony Delroy
  • 94,554
  • 11
  • 158
  • 229
0

It simply means that the wrapper can be passed to the client and the client must work well with the wrapper, without knowing the concrete type of the wrapper. The client just needs to know the interface in which the wrapper is implementing.

I think the author of the wiki article is somehow verbose here.

Nghia Bui
  • 3,454
  • 11
  • 21