设计模式之装饰器 Decorator Pattern

1. 定义

当需要扩展子类中的功能时,不修改原有子类A中的功能,采用继承自同一个父类新子类B,来增加原有子类A中功能。此时需要新的子类B持有子类A的引用。

2. 解释

设计原则

  1. 对扩展开放,对修改封闭;
  2. 使用组合(接口)代替继承;

装饰模式特点:

  1. 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
  2. 装饰对象包含一个真实对象的引用(reference)
  3. 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
  4. 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

装饰器模式与其他组合模式类似,不同的地方在于,装饰器模式没有引入其他父类型,即可实现运行时的行为扩展。
与其他设计模式的比较:[Design Pattern] Decorator 裝飾者模式

3. 举例

#include <iostream>
#include <memory>

using namespace std;

class Ship : public enable_shared_from_this<Ship> {
public:
  virtual void run() = 0;
  virtual void shot() = 0;
  virtual ~Ship() = default;

  std::shared_ptr<Ship> getptr() {
    return shared_from_this();
  }
};

class NorthCarolina : public Ship {
public:
  void run() override {
    cout << "NorthCarolina is running." << endl;
  };
  void shot() override {
    cout << "NorthCarolina is shotting." << endl;
  };
};

class Iowa : public Ship {
public:
  void run() override {
    cout << "Iowa is running." << endl;
  };
  void shot() override {
    cout << "Iowa is shotting." << endl;
  };
};

class Decorator : public Ship {
public:
  Decorator(std::shared_ptr<Ship> ship) : ship(ship) {}
  void run() override {
    ship->run();
  }
  void shot() override {
    ship->shot();
  }

protected:
  std::shared_ptr<Ship> ship;
};

class ScoutPlane : public Decorator {
  string scout;

public:
  ScoutPlane(std::shared_ptr<Ship> ship) : Decorator(ship) {}
  void setScout() {
    scout = "Searching......";
  };
  void getScout() {
    cout << scout << endl;
  }
  void run() override {
    ship->run();
    setScout();
    getScout();
  }
  void shot() override {
    ship->shot();
  }
};

class Ammu : public Decorator {
  string ammu;

public:
  Ammu(std::shared_ptr<Ship> ship) : Decorator(ship) {}
  void setAmmu() {
    ammu = "AP";
  };
  void getAmmu() {
    cout << "shotting " << ammu << "." << endl;
  }
  void run() override {
    ship->run();
  }
  void shot() override {
    ship->shot();
    setAmmu();
    getAmmu();
  }
};
int main() {
  std::shared_ptr<Ship> ship1 = std::make_shared<Iowa>();
  std::shared_ptr<Ship> ship2 = std::make_shared<NorthCarolina>();

  ship1->run();
  ship1->shot();
  cout << "----------------" << endl;

  ship2->run();
  ship2->shot();
  cout << "----------------" << endl;

  std::shared_ptr<Ship> ship3 = std::make_shared<Ammu>(ship1->getptr());
  ship3->run();
  ship3->shot();
  cout << "----------------" << endl;

  std::shared_ptr<Ship> ship4 = std::make_shared<ScoutPlane>(ship3->getptr());
  ship4->run();
  ship4->shot();
  cout << "----------------" << endl;

  std::shared_ptr<Ship> ship5 = std::make_shared<ScoutPlane>(ship2->getptr());
  ship5->run();
  ship5->shot();
}
Iowa is running.
Iowa is shotting.
----------------
NorthCarolina is running.
NorthCarolina is shotting.
----------------
Iowa is running.
Iowa is shotting.
shotting AP.
----------------
Iowa is running.
Searching......
Iowa is shotting.
shotting AP.
----------------
NorthCarolina is running.
Searching......
NorthCarolina is shotting.
posted @ 2022-10-25 13:32  山岚2013  阅读(4)  评论(0编辑  收藏  举报