类之间的组合关系

2023-05-16

 继承加复合

这种情况下的构造顺序是:先调用Base的默认构造函数,再调用Component的构造函数,最后调用自己的构造函数。

析构的顺序与之相反,先调用自己析构函数,再调用Component的析构函数,最后调用Base的析构函数。

这种情况下构造由内而外,析构由外而内。

委托加继承

考虑一种应用,我们想同时多窗口打开一份ppt然后进行编辑:

设计的类:


class Subject
{
    int m_value;
    vector<Observer*> m_views;
public:
    void attach(Observer* obs)
    {
      m_views.push_back(obs);
    }
    void set_val(int value)
    {
      m_value = value;
      notify();
    }
    void notify()
    {
      for (int i = 0; i < m_views.size(); ++i)
        m_views[i]->update(this, m_value);
    }
};  

class Observer
{
public:
    virtual void update(Subject* sub, int value) = 0;
};  

attach是将数据和观察者绑定;  

notify函数遍历所有的观察者。  

Subject和Observer之间就是委托的关系,而Observer是一个Base class 可以被继续继承下去:  

Composite

考虑下面的例子Composite中有vector,元素既可能是Primitive也可能是Composite,所以,我们在此添加它们共同的Base class Composite的指针。

add 的设计与上面的考虑相同。

这种解法也称为Composite。

对应的代码:


class Component
{
    int value;
public:
    Component(int val) { value = val; }
    virtual void add( Component* ) { }
};

class Primitive: public Component
{
public:
    Primitive(int val): Component(val) {}
}

class Composite: public Component
{
    vector <Component*> c;
public:
    Composite(int val): Component(val) { }
    void add(Component* elem) {
    c.push_back(elem);
    }
    …
};  

Component中的add写成空函数,Primitive中就不是必须要重写这个函数,而Composite之中可以按实际进行定义。

Prototype

如果想设计一个框架类,又想获取未来定义的子类,

在这里,每个子类中都有一个静态的自己,例如LSTA:LandSatImage,子类中的clone函数会返回一个子类本身,addPrototype函数返回子类对象,findAndClone函数将找到子类对象并且创建一个副本。

代码:


#include <iostream.h>
enum imageType
{
LSAT, SPOT
};
class Image
{
public:
    virtual void draw() = 0;
    static Image *findAndClone(imageType);
    protected:
    virtual imageType returnType() = 0;
    virtual Image *clone() = 0;
    // As each subclass of Image is declared, it registers its prototype
    static void addPrototype(Image *image)
    {
    _prototypes[_nextSlot++] = image;
    }
private:
    // addPrototype() saves each registered prototype here
    static Image *_prototypes[10];
    static int _nextSlot;
};
Image *Image::_prototypes[];
int Image::_nextSlot;

// Client calls this public static member function when it needs an instance
// of an Image subclass
Image *Image::findAndClone(imageType type)
{
for (int i = 0; i < _nextSlot; i++)
    if (_prototypes[i]->returnType() == type)
    return _prototypes[i]->clone();
}  

class  LandSatImage: public Image
{
public:
    imageType returnType() {
        return LSAT;
        }
    void draw() {
        cout << "LandSatImage::draw " << _id << endl;
        }
    // When clone() is called, call the one-argument ctor with a dummy arg
    Image *clone() {
        return new LandSatImage(1);
        }
    protected:
    // This is only called from clone()
    LandSatImage(int dummy) {
    _id = _count++;
}
private:
    // Mechanism for initializing an Image subclass - this causes the
    // default ctor to be called, which registers the subclass's prototype
    static LandSatImage _landSatImage;
    // This is only called when the private static data member is inited
    LandSatImage() {
    addPrototype(this);
    }
    // Nominal "state" per instance mechanism
    int _id;
    static int _count;
};
// Register the subclass's prototype
LandSatImage LandSatImage::_landSatImage;
// Initialize the "state" per instance mechanism
int LandSatImage::_count = 1;  

class SpotImage: public Image
{
public:
    imageType returnType() {
        return SPOT;
        }
    void draw() {
        cout << "SpotImage::draw " << _id << endl;
        }
    Image *clone() {
        return new SpotImage(1);
        }
    protected:
    SpotImage(int dummy) {
        = _count++;
    }
private:
    SpotImage() {
        addPrototype(this);
        }
    static SpotImage _spotImage;
    int _id;
    static int _count;
};
SpotImage SpotImage::_spotImage;
int SpotImage::_count = 1;  

// Simulated stream of creation requests
const int NUM_IMAGES = 8;
imageType input[NUM_IMAGES] =
{
    LSAT, LSAT, LSAT, SPOT, LSAT, SPOT, SPOT, LSAT
};

int main()
{
    Image *images[NUM_IMAGES];
    // Given an image type, find the right prototype, and return a clone
    for (int i = 0; i < NUM_IMAGES; i++)
        images[i] = Image::findAndClone(input[i]);
    // Demonstrate that correct image objects have been cloned
    for (i = 0; i < NUM_IMAGES; i++)
        images[i]->draw();
    // Free the dynamic memory
    for (i = 0; i < NUM_IMAGES; i++)
        delete images[i];
}  

转载于:https://www.cnblogs.com/xiaojianliu/articles/9497415.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

类之间的组合关系 的相关文章

  • java-生产者消费者问题以及解决办法

    文章目录 1 生产者消费者问题概述2 生产者消费者问题的解决办法2 1 解决思路2 2 实现方法2 3 代码实现2 3 1 wait 和nofity 方法2 3 2 await signal 方法2 3 3 BlockingQueue阻塞队
  • 【Remote Development】VSCode 基于 SSH 进行远程开发

    系统需求 我们在 VSCode 下载由微软官方推出的 Remote SSH 插件 查看一下里面的描述 xff0c 对于远程机器的要求如下 xff1a Local A supported OpenSSH compatible SSH clie
  • git idea创建新分支,获取/合并主支代码的2个方法

    其他sql格式也在更新中 xff0c 可直接查看这个系列 xff0c 要是没有你需要的格式 xff0c 可在评论或私信我 个人目录 获取主支代码的2个方法 1 xff0c 创建一个分支 xff0c 获取主支的所有代码 xff08 场景 xf
  • spring手把手超详细讲解(基本配置,基于xml)

    spring教程 1 1 容器概述1 1 1 配置元数据1 1 2 容器的实例化1 1 3 容器的使用 1 2 bean的概述1 2 1 命名bean1 2 2 实例化Bean 1 3 依赖1 3 1 依赖注入1 3 2 使用 属性1 3
  • 18.5 重载全局new、delete、定位new及重载等

    一 xff1a 重载全局operator new和operator delete操作符 span class token macro property span class token directive hash span span cl
  • java进程占用CPU过高常见的两种情况及分析定位

    java进程爆cpu的快速定位 1 背景 在程序开发的过程中 xff0c 难免遇到进程占用cpu过高 xff08 现网居多 开发环境 xff09 的情况 xff0c 现网出现这种情况就需要及时的能定位到问题 xff0c 快速解决 xff0c
  • 【Android ViewBinding】内存泄露

    场景 在MainActivity中分别加载两个Fragment处理业务 首先触发加载SecondFragment xff1a MainActivity触发 supportFragmentManager commit add R id con
  • Shell小脚本实现一键关机/重启虚拟机

    利用Shell脚本实现一键关机 重启虚拟机 xff0c 解决每次虚拟机关机或重启都需要手动一个个关机或重启的烦恼 xff01 1 脚本一 xff1a shut sh span class token comment bin bash spa
  • LAMP环境搭建

    前言 一 在虚拟机上安装Linux系统 二 安装Apache 1 下载好后 xff0c 看了看版本 xff0c 不是太老 xff0c 就没有继续安装 2 开启Apache服务 3 设置Apache开机启动服务 4 尝试一下是否启动了服务 x
  • 小程序跳坑之安卓真机不能访问服务器的问题

    因为一项目 xff0c 有几个页面都需要访问服务器 xff0c 从服务器上下载数据 xff0c 在苹果和开发者工具上都运行完美 xff0c 唯独一款安卓手机 xff0c 访问不了 xff0c 经测试 xff0c 发现是汉字编码问题 xff0
  • python Tkinter 界面button调用多进程函数,弹出多个相同界面

    这是我的界面button command的函数start simulate 这是我的多进程函数 xff1a 点击之后 xff0c 弹出多个相同界面 把调用多进程的函数在 if name 61 61 39 main 39 这里调用就不会出现多
  • python入门之if-else语句

    文章目录 一 if语句二 elif语句三 if嵌套语句四 else语句1五 else语句2六 if else语句举例1七 if else语句举例2 一 if语句 span class token keyword if span False
  • Ubuntu 16.04 远程桌面

    1 安装xrdp sudo apt get install xrdp 2 安装vnc4server 我这里是安装xrdp的时候自动安装的 我看网上很多说是需要单独安装的 3 安装xfce4 sudo apt get install xubu
  • GitLab端口冲突 解决办法

    访问gitlab xff0c 出现 xff1a 502 GitLab在使用的过程中 xff0c 会开启80端口 xff0c 如果80端口被其他的应用程序占用 xff0c 则GitLab的该项服务不能使用 xff0c 所以访问GitLab会失
  • Android开发 之 确认凭证

    确认凭证 主要目的 xff1a 设置不用验证时间 设置为30秒 xff0c 当超过30秒后则需要重新验证身份才能操作 您的应用可以根据用户在多久之前最后一次解锁设备来验证其身份 此功能让用户不必费心记忆应用特定密码 xff0c 您也无需实现
  • inner join、outer join、right join、left join 之间的区别

    inner join outer join right join left join 之间的区别 一 sql的left join right join inner join之间的区别 left join 左联接 返回包括左表中的所有记录和右
  • "大泥球"仍然是最常见的软件设计

    大泥球 xff0c 是指杂乱无章 错综复杂 邋遢不堪 随意拼贴的大堆代码 这些年来 xff0c 为了对付这个泥球 xff0c 我们看到了多种指导方法 xff0c 比如SOLID GRASP 和KISS xff0c 与其他诸多年代久远的 提倡
  • 3322.org带来的麻烦

    大概是3322 org被短时间攻破 xff0c 下载他的动态域名客户端的时候下到一个病毒Trojandropper js adagent gd xff0c 把江民关了 xff0c 并且再也开不开 系统还原不行 xff0c 安全模式也进不去
  • Qt学习笔记:多线程的使用

    文章目录 前言1 何时使用线程2 QThread类实现多线程2 1 多线程的实现方法2 2 线程休眠2 3 正确结束线程 3 线程同步3 1 互斥量3 2 信号量3 3 条件变量 4 线程池参考资料 前言 程序中调用耗时的操作 xff08
  • 上位机开发笔记:环形缓冲区

    文章目录 前言1 环形缓冲区工作机制1 1 实现原理1 2 区分缓冲区满或者空1 总是保持一个存储单元为空2 使用计数数据3 镜像指示位 2 Qt实现环形缓冲区2 1 QByteArray环形缓冲区2 2 QSemaphore实现环形缓冲区

随机推荐

  • IDEA搭建Spring框架环境

    IDEA搭建Spring框架环境 一 spring 框架概念 spring 是众多开源 java 项目中的一员 xff0c 基于分层的 javaEE 应用一站式轻量 级开源框架 xff0c 主要核心是 Ioc 控制反转 依赖注入 与 Aop
  • SQL SERVER中索引类型包括的三种类型分别是

    xfeff xfeff 唯一索引 UNIQUE 聚集索引 CLUSTERED xff09 非聚集索引 NONCLUSTERED xff09 主键与唯一索引的区别 主键是一种约束 xff0c 唯一索引是一种索引 xff0c 两者在本质上是不同
  • _Linux多线程--生产者消费者模型篇

    文章目录 1 为何要使用生产者消费者模型2 基于BlockingQueue的生产者消费者模型3 C 43 43 queue模拟阻塞队列的生产消费模型条件变量使用规范简单测试1 BlockQueue 缓存 超市 2 ConProd cc3 结
  • HTTP、TCP的关系及状态码

    一 基本概念 1 TCP连接 手机能够使用联网功能是因为手机底层实现了TCP IP协议 xff0c 可以使手机终端通过无线网络建立TCP连接 TCP协议可以对上层网络提供接口 xff0c 使上层网络数据的传输建立在 无差别 的网络之上 建立
  • x299平台装linux系统的一些天坑

    年前实验室为了配置大内存的服务器 xff0c 受限于经费 xff0c 我们只能使用比较便宜的游戏板 xff0c 选择了微星的x299平台 xff0c 买回来自带win10 xff0c 回来的第一件事就是装linux xff0c 习惯上我会装
  • android的应用包名与代码包名

    说来惭愧 xff0c 好歹还是做了android应用这么久了 xff0c 居然不知道这个事情 参考 xff1a http www xmumu com post 2013 08 05 40052300660 http blog javia o
  • [自动驾驶]Build a Traffic Sign Recognition Program

    看 准确率98 的深度学习交通标志识别是如何做到的 xff1f 这篇文章的时候 xff0c 发现了udacity的自动驾驶课程 可惜要收费 xff0c 不过课程project在github上有 xff0c 那直接做project就好了 xf
  • Spring MVC框架的高级配置

    本文将为您提供关于Spring MVC框架的配置技巧 xff0c 以帮助管理基于Spring的web应用程序的多个实例 本配置管理主题常被学术界所忽略 xff0c 但是 xff0c 这对于现实的web开发尤为重要 本主题并不直接关联任何具体
  • ffmpeg解码花屏

    问题 xff1a 解码为YUV420转为Bitmap后显示在屏幕上时 xff0c 有三分之二为花屏 xff1a 如图 xff1a 首先用h264Visa分析帧 xff1a 已经读出了sps等信息 xff0c 这些信在解码第一帧时被写入环境变
  • 使用Hexo+Github一步步搭建属于自己的博客(基础)

    前言 xff1a 电脑系统为window 10专业版 xff0c 64位 相关步骤 xff1a 1 安装Node js和配置好Node js环境 xff0c 打开cmd命令行 xff0c 成功界面如下 2 安装Git和配置好Git环境 xf
  • OpenSSL命令学习

    OpenSSL命令学习 一 基础概念 OpenSSL是一个开放源代码的软件库包 xff0c 应用程序可以使用这个包来进行安全通信 xff0c 避免窃听 xff0c 同时确认另一端连接者的身份 这个包广泛被应用在互联网的网页服务器上 下面以问
  • 论文阅读——Shadow Attacks:Hiding and Replacing Content in Signed PDFS

    论文阅读报告 Shadow Attacks xff1a Hiding and Replacing Content in Signed PDFS 阅读背景 本次阅读的论文是由Christian Mainka Vladislav Mladeno
  • SecKill——一款超级好用的抢单软件

    软件介绍 下载地址见文章末尾 Seckill是一款使用Python和pyqt编写 xff0c 利用selenium库实现的自动化抢单软件 xff0c 它界面友好 xff0c 使用方便 xff0c 可以帮助你在购物时快人一步 xff0c 及时
  • 获取PowerShell的所有历史记录

    PowerShell默认的history命令只能查看当前窗口的历史记录 xff0c 很不方便 可以使用以下方法获取PowerShell的所有历史记录 xff0c 简单记录一下 一 PSReadline 当前版本 xff08 5 1 xff0
  • 用pyqt5写一个同步文件夹内容的小工具

    详见https github com distiny cool File Synchronization 完整代码在最下面 同步文件夹内容的小工具 点这里直接下载可执行程序 出发点 打算把电脑上的文件备份到外部磁盘上面 xff0c 但是原来
  • 博客园添加GitHub链接

    添加该样式涉及到博客园后台页面定制CSS代码和页首Html代码两处改动 1 将下列CSS代码添加至页面定制CSS代码处 1 GitHub Cornor 2 github corner hover octo arm 3 animation o
  • SQL-修改表名,列名

    sql 1 sql server修改表名 列名 修改表名 xff1a EXEC sp rename 原有表名 39 新表名 39 修改列名 xff1a EXEC sp rename 表名 原有列名 新列名 39 39 COLUMN 39 如
  • 程序员你为什么迷茫?

    你曾经充满热情 xff0c 是一位开源软件倡导者 xff0c 你崇尚全栈工程师才有未来的理念 xff0c 你渴望改变世界 但是现在你每天都处于焦虑之中 xff0c 你每天不断地学习各种技术Kotlin Swift React Native
  • Dataset之COCO数据集:COCO数据集的简介、下载、使用方法之详细攻略

    COCO数据集的简介 MS COCO的全称是Microsoft Common Objects in Context xff0c 起源于微软于2014年出资标注的Microsoft COCO数据集 xff0c 与ImageNet竞赛一样 xf
  • 类之间的组合关系

    继承加复合 这种情况下的构造顺序是 xff1a 先调用Base的默认构造函数 xff0c 再调用Component的构造函数 xff0c 最后调用自己的构造函数 析构的顺序与之相反 xff0c 先调用自己析构函数 xff0c 再调用Comp