《C++20设计模式》---原型模式学习笔记代码

C++20设计模式

第 4 章 原型模式

学习笔记

笔记代码

cpp 复制代码
#include<iostream>
#include<string>

// #define VALUE_OF_ADDRESS // PP_4_2_1 (no define: PP_4_2_2)
namespace PP_4_2 {
    class Address
    {
    public:
        std::string street;
        std::string city;
        int suite;
        // Address(std::string& street, std::string& city, int suite)
        //     :street(street), city(city), suite(suite) {
        // }
    };

    class Contact
    {
    public:
        std::string name;
#ifdef VALUE_OF_ADDRESS
        Address address;
#else
        Address* address;
        ~Contact() {
            // 由于存在double free问题, 这块作为测试就不释放内存了
            // delete address;
        }
#endif
    };

    void testOrdinaryCopy() {
#ifdef VALUE_OF_ADDRESS
        // here is the prototype
        Contact worker{"", {"123 East Dr", "London", 0}};

        // make a copy pf prototype and customize it
        Contact john = worker;
        john.name = "John Doe";
        john.address.suite = 10;
#else
        // 下面代码会发生异常,原因是因为存在多次释放Address对象
        // here is the prototype
        Contact worker{"",new Address{"123 East Dr", "London", 0}};
        // make a copy pf prototype and customize it
        Contact john = worker;
        john.name = "John Doe";
        john.address->suite = 10;
#endif
    
    }
} // PP_4_2

namespace PP_4_3 {
    class Address
    {
    public:
        std::string street;
        std::string city;
        int suite;

        Address(){}
        Address(std::string street, std::string city, int suite)
            :street(street), city(city), suite(suite) {
        }
    };

    class Contact
    {
    public:
        std::string name;
        Address *address;

        Contact(){}
        Contact(std::string name, Address *address) : name(name), address(address) {}
        Contact(const Contact& other)
            :name(other.name), address(new Address(*other.address)) { // 这里的会调用Address的默认拷贝构造函数
                // address = new Address{
                // other.address->street,
                // other.address->city,
                // other.address->suite
        }

        Contact operator=(const Contact& other) {
            if (this == &other) {
                return *this;
            }

            name = other.name;
            address = other.address;

            return *this;
        }

        ~Contact() {delete address;}
    };

    void testCopyConstructor() {
        Contact worker{"",new Address{"123 East Dr", "London", 0}};
        // Contact john;
        // john = worker;
        Contact john = worker;
        john.name = "john";
        john.address->suite = 10;
    }
} // PP_4_3

namespace PP_4_4 {
    class Address
    {
    public:
        std::string street;
        std::string city;
        int suite;

        Address(){}
        Address(std::string street, std::string city, int suite)
            :street(street), city(city), suite(suite) {
        }

        virtual Address* clone() {
            return new Address{street, city, suite};
        }
    };

    class ExtendedAddress : public Address {
    public:
        std::string country;
        std::string postcode;

        ExtendedAddress(const std::string& street, const std::string& city, 
            const int suite, const std::string& country,
            const std::string& postcode):Address(street, city, suite), country(country) {
        }

        ExtendedAddress* clone()override {
            return new ExtendedAddress(street, city, suite, country, postcode);
        }
    };

    void testVirtualConstructor() {
        std::cout << __FUNCTION__ <<"() begin.";
        ExtendedAddress ea{"123 East Dr", "London", 0, "UK", "SW101EG"};
        Address& a = ea; //upcast
        auto cloned = a.clone();
        Address xx;

        printf("\nea: %s\n", typeid(ea).name());
        printf("a: %s\n", typeid(a).name());
        printf("cloned: %s\n", typeid(cloned).name());
        printf("cloned: %s\n", typeid(xx).name());

        std::cout << __FUNCTION__ <<"() end.\n\n";
    }
} // PP_4_4

#include<memory>
namespace PP_4_6
{
    class Address
    {
    public:
        std::string street;
        std::string city;
        int suite;

        Address() {}
        Address(std::string street, std::string city, int suite)
            : street(street), city(city), suite(suite)
        {
        }

        virtual Address *clone()
        {
            return new Address{street, city, suite};
        }
    };

    class Contact
    {
    public:
        std::string name;
        Address *address;

        Contact() {}
        Contact(std::string name, Address *address) : name(name), address(address) {}
        Contact(const Contact &other)
            : name(other.name), address(new Address(*other.address))
        {
        }

        Contact operator=(const Contact &other)
        {
            if (this == &other)
            {
                return *this;
            }

            name = other.name;
            address = other.address;

            return *this;
        }

        ~Contact() { delete address; }
    };

    class EmployeeFactory {
        static Contact main;
        static Contact aux;

        static std::unique_ptr<Contact> NewEmployee(std::string name,
            int suite, Contact& proto) {
            auto result = std::make_unique<Contact>(proto); //这里会调用拷贝构造
            result->name = name;
            result->address->suite = suite;
            return result;
        }

    public:
        static std::unique_ptr<Contact> NewMainOfficeEmployee(
            std::string name , int suite) {
            return NewEmployee(name, suite, main);
        }

        static std::unique_ptr<Contact> NewAuxMainOfficeEmployee(
            std::string name, int suite) {
            return NewEmployee(name, suite, aux);
        }
    };

    Contact EmployeeFactory::main{"", new Address{"123 East Dr", "London", 0}};
    Contact EmployeeFactory::aux{"", new Address{"123B East Dr", "London", 0}};

    void testPrototypeFactory() {
        auto john = EmployeeFactory::NewMainOfficeEmployee("John Doe", 123);
        auto jane = EmployeeFactory::NewAuxMainOfficeEmployee("Jane Doe", 125);
    }

} // PP_4_6

int main()
{
    PP_4_2::testOrdinaryCopy();
    PP_4_3::testCopyConstructor();
    PP_4_4::testVirtualConstructor();
    PP_4_6::testPrototypeFactory();
    return 0;
}
相关推荐
海特伟业8 小时前
隧道调频广播覆盖-隧道调频广播无线覆盖系统建设要点、难点分析与解决应对
运维·设计模式
sg_knight8 小时前
设计模式实战:享元模式(Flyweight)
python·设计模式·享元模式·flyweight
Swift社区11 小时前
AI 时代,ArkUI 的设计模式会改变吗?
人工智能·设计模式
数据中穿行11 小时前
访问者设计模式全方位深度解析
设计模式
宁雨桥11 小时前
前端设计模式面试题大全
前端·设计模式
数据中穿行12 小时前
迭代器设计模式全方位深度解析
设计模式
数据中穿行12 小时前
观察者设计模式全方位深度解析
设计模式
程序员Terry13 小时前
别老写重复代码了!模版方法模式一次讲透
java·设计模式
数据中穿行13 小时前
建造者模式全方位深度解析
设计模式