草庐IT

DesignPattern-part3

sunstrike's blog 2023-03-28 原文
title: "modern C++ DesignPattern-Part3"
date: 2018-04-12T19:08:49+08:00
lastmod: 2018-04-12T19:08:49+08:00
keywords: [设计模式, C++]
tags: [设计模式]
categories: []

结构式设计模式的最后两个,享元模式:实现对象共享,减少内存开销;代理模式,提供相同接口的代理

flyweight

享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。boost::flyweight使用:

struct User2
{
  flyweight<string> first_name, last_name;  //类似一个缓存

  User2(const string &first_name, const string &last_name)
    : first_name(first_name),
      last_name(last_name) {}
};

void boost_flyweight()
{
  User2 user1{"John", "Smith"};
  User2 user2{"Jane", "Smith"};
  cout << user1.first_name << endl;
  cout << boolalpha  //std::boolalpha可以把bool变成true/false字符串
       << (&user1.first_name.get() == &user2.first_name.get()) << endl;
  cout << boolalpha
       << (&user1.last_name.get() == &user2.last_name.get()) << endl;
}

示例:

class FormattedText {  //用来记录是否被复用的单元
    string plain_text;
    bool *caps;
public:
    explicit FormattedText(const string &plainText)
            : plain_text{plainText} {
        caps = new bool[plainText.length()];
        memset(caps, 0, plain_text.length());
    }

    ~FormattedText() {
        delete[] caps;
    }

    void capitalize(int start, int end) {
        for (int i = start; i <= end; ++i)
            caps[i] = true;
    }

    friend std::ostream &operator<<(std::ostream &os, const FormattedText &obj) {
        string s;
        for (int i = 0; i < obj.plain_text.length(); ++i) {
            char c = obj.plain_text[i];
            s += (obj.caps[i] ? toupper(c) : c);
        }
        return os << s;
    }
};

class BetterFormattedText {
public:
    struct TextRange {
        int start, end;
        bool capitalize, bold, italic;

        bool covers(int position) const {
            return position >= start && position <= end;
        }
    };

    TextRange &get_range(int start, int end) { //每当设置一个被复用的单元,push到vector里面,返回最后一个
        formatting.emplace_back(TextRange{start, end});
        return *formatting.rbegin();
    }

    explicit BetterFormattedText(const string &plainText)
            : plain_text{plainText} {
    }

    friend std::ostream &operator<<(std::ostream &os, const BetterFormattedText &obj) {
        string s;
        for (size_t i = 0; i < obj.plain_text.length(); i++) {
            auto c = obj.plain_text[i];
            for (const auto &rng : obj.formatting) {
                if (rng.covers(i) && rng.capitalize)
                    c = toupper(c);
            }
            s += c; // fixed!
        }
        return os << s;
    }

private:
    string plain_text;
    vector<TextRange> formatting;
};

Proxy

代理模式最经典的是shared_ptr实现,增加了引用计数的同时保持了原有的普通指针接口

Property Proxy

template <typename T> struct Property {
  T value;
  Property(const T initialValue) {
    *this = initialValue;
  }
  operator T() {  //getter
    return value;
  }
  T operator =(T newValue) {  //setter
    return value = newValue;
  }
};
//usage
struct Creature
{
  Property<int> strength{ 10 };
  Property<int> agility{ 5 };
};
void property_proxy() {
  Creature creature;
  creature.agility = 20;
  cout << creature.agility << endl;
}

主要目的是可以允许 Property<int>与int的随时转换。

Virtual Proxy

这种非常常见,使用时分两种,eager模式和lazy模式,区别就是lazy模式是在使用的时候才会初始化

struct Image{
  virtual ~Image() = default;
  virtual void draw() = 0;
};
struct Bitmap : Image{
  Bitmap(const string& filename) {
    cout << "Loading image from " << filename << endl;
  }
  void draw() override {
    cout << "Drawing image" << endl;
  }
};
struct LazyBitmap : Image {
  LazyBitmap(const string& filename): filename(filename) {}
  ~LazyBitmap() { delete bmp; }
  void draw() override {
    if (!bmp)
      bmp = new Bitmap(filename);
    bmp->draw();
  }
private:
  Bitmap* bmp{nullptr};
  string filename;
};

void draw_image(Image& img) {
  img.draw();
}
void virtual_proxy() {
  LazyBitmap img{ "pokemon.png" };
  draw_image(img); // loaded whether the bitmap is loaded or not
  draw_image(img);
}

有关DesignPattern-part3的更多相关文章

  1. day1-数组part01| 704. 二分查找、27. 移除元素 - 2

    数组理论基础数组是存放在连续内存空间上的相同类型数据的集合。数组下标从0开始数组内存空间的地址是连续的c++中vector和array的区别1、vector是顺序容器,其利用连续的内存空间来存储元素,但是其内存空间大小是能够改变的。2、array是顺序容器,其也是利用连续的内存空间来存储元素,但它的内存空间是固定大小的,申请之后就无法改变。3、vector的底层是array实现的二维数组二维数组在内存的空间地址是连续的704|二分查找思路1、把整个数组一分为二;2、判断目标值在左区间还是右区间,若在左区间,则修改右区间指针的位置;若在右区间,则修改新区间的左区间位置3、重复上述过程,直到lef

  2. ruby 心印 : explicit scoping on a class definition part 2 - 2

    我想澄清这个原始post的一些事情.答案建议Ruby按以下顺序搜索常量定义:封闭范围任何外部范围(重复直到达到顶层)包含的模块父类(superclass)对象内核所以澄清一下,在第(1-6)步是为legs_in_oyster找到的常量LEGS的值?它来自父类(superclass)Animal吗?类MyAnimals的范围是否因为不被视为封闭范围而被忽略?这是由于明确的MyAnimals::Oyster类定义吗?谢谢!只是想了解。这是代码:classAnimalLEGS=4deflegs_in_animalLEGSendclassNestedAnimaldeflegs_in_neste

  3. javascript - 如何测试一个字符串是否是另一个字符串的最后一个 “part”? - 2

    varlongString="thisstringislongbutwhy"varshortString="butwhy"我如何测试shortString是否不仅包含在longString中而且实际上是字符串的最后一部分。我使用indexOf==0来测试字符串的开头,但不确定如何获取它的结尾 最佳答案 你不需要正则表达式,如果它是javascript你可以这样做:longString.endsWith(shortString) 关于javascript-如何测试一个字符串是否是另一个字符

  4. javascript - 如何检测鼠标是否在:before or over the :after part of an element上方 - 2

    我有这个CSS来定义放置区域,用户可以在现有部分之前或之后放置一个部分。.section:before,.section:after{content:"[inserthere]";height:64px;line-height:56px;width:100%;display:block;border:3pxdashed#aaa;}这里使用JavaScript+JQuery是放置监听器,它检测当前鼠标下的元素:elem.on('drop',function(e){e.preventDefault();varcontainer=$(elem[0].elementFromPoint(e.cl

  5. javascript - Crockford 的 hanoi 函数(来自 "The Good Parts") - 2

    这个问题在这里已经有了答案:HowdoesrecursivealgorithmworkforTowersofHanoi?(2个答案)关闭8年前。目前,我正在阅读道格拉斯·克罗克福德(DouglasCrockford)的书,汉诺塔的功能让我有点头疼。即使在控制台上记录了一些东西,我也无法真正理解发生了什么。这是我添加的功能:varhanoi=function(disc,src,aux,dst){console.log(disc);console.log(src,dst);if(disc>0){hanoi(disc-1,src,dst,aux);console.log('Movedisc'

  6. javascript - 观察一个JS事件,当你只知道事件名称的PART? - 2

    我继承了一些触发一堆事件的JS(我无法更改):jQuery(document).trigger('section:'+section);//where"section"changesdynamically我想观察所有这些事件,解析出section的值,并根据它的内容做一些不同的事情。如果它没有改变,我可以这样做:jQuery(document).on('section:top',doStuff);但是,如果我只知道事件名称的第一部分,我该如何观察该事件呢? 最佳答案 不幸的是,您不能以$().on('section:*')的样式监听

  7. 正则表达式 : Match text NOT part of a HTML tag - 2

    我真的想要一个在node.js中可执行的正则表达式(所以没有jQueryDOM处理等,因为标签可以有不同的嵌套)匹配所有不是HTML标签或部分的文本它分成不同的组。例如我想匹配"5","ELT.","SPR","","plo","Unterricht",""," "和"plo"来自那个字符串:5ELT.SPR pioUnterricht  pio我可以保证标签中不会有“>”。我找到的解决方案是(?)[^>,但这在node.js中不起作用(可能是因为前瞻?它说“无效组”)有什么建议吗?(是的,我真的认为Regex是正确的方式,因为html可能以其他方

  8. 【全栈计划 —— 单片机】——Part_04 IO口输入功能的使用 - 2

    文章目录前言独立按键实验💒项目代码及效果🌟刨根问底环节🌻浅识按键代码设计矩阵按键实验💒项目代码及效果🌟刨根问底环节🌻浅识矩阵按键代码设计浅读代码总结前言杨枝的单片机专栏,多图多阐述,争取让大家在学习单片机的路上减少些许的痛苦虽说是14天,但是我自己快更了半个月了,也才更了一半,我看了一下后面的知识,可以拎出来说的不是特别多啦,我已经在买STM32的板子啦,咱们重心还是得放在32~14天了,是对于各位看这个篇文章的小伙伴来说嗷,一天看一篇,轻松上手,不再害怕单片机。因为我自己现在呢,抬头是算法题海,低头是作业项目,很多时候只是写得完草稿,没有及时发出来,抱歉哈,原谅我🌹🌹🌹独立按键实验💒项目代码

  9. javascript - 如何剥离数据 :image part from a base64 string of any image type in Javascript - 2

    我目前正在执行以下操作以在Javascript中解码base64图像:varstrImage="";strImage=strToReplace.replace("data:image/jpeg;base64,","");strImage=strToReplace.replace("data:image/png;base64,","");strImage=strToReplace.replace("data:image/gif;base64,","");strImage=strToReplace.replace("data:image/bmp;base64,","");正如您在上面看到的

  10. javascript - "JavaScript - the Good Parts"示例的解释(第 4.15 节)? - 2

    JS初学者:)需要来自Crockford'sbook的代码片段的解释,第4.15节:varmemoizer=function(memo,fundamental){varshell=function(n){varresult=memo[n];if(typeofresult!=='number'){result=fundamental(shell,n);memo[n]=result;}returnresult;};returnshell;};varfibonacci=memoizer([0,1],function(shell,n){returnshell(n-1)+shell(n-2);}

随机推荐