浅谈C++设计模式之工厂方法(Factory Method)

  为什么要用设计模式?根本原因是为了代码复用,增加可维护性。

  面向对象设计坚持的原则:开闭原则(Open Closed Principle,OCP)、里氏代换原则(Liskov Substitution Principle,LSP)、依赖倒转原则(Dependency Inversion Principle,DIP)、接口隔离原则(Interface Segregation Principle,ISP)、合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)、最小知识原则(Principle of Least Knowledge,PLK,也叫迪米特法则)

  • 开闭原则:模块应该对扩展开放,而对修改关闭。也就是说,在不修改原来的代码的前提下进行扩展。
  • 里氏代换原则:如果调用的是父类的话,那么换成子类也完全没有问题。
  • 依赖倒转原则:尽量针对接口编程,而不是针对实现编程。通过抽象父类的指针来调用子类的实现。
  • 接口隔离原则:每个接口应该只有一种角色,多个角色应该用多个接口来实现。
  • 合成/聚合复用:在新的对象中尽量使用已有的对象,使新对象向这些对象委派来达到复用已有功能的目的,而不是通过继承来实现。
  • 最少知识原则:一个对象应对其它对象有尽可能少的了解。

  上述的这些原则也正是体现了OOP高内聚、低耦合的基本原则,最终目的都是为了代码复用,增加可维护性。设计模式就是本着这些原则来进行OOP设计的一些方法。

  设计模式开篇先来介绍工厂方法(Factory Method)模式

  对象创建型模式的一种。工厂方法是定义一个用于创建对象的接口,让子类决定实例化哪一个类,让一个类的实例化延迟到它的子类中。

  • 客户Client
  • 工厂接口Creator
  • 工厂实现类ConcreteCreatorP1和ConcreteCreatorP2
  • 产品接口Product
  • 产品实现类ConcreteProductP1和ConcreteProductP2

  上面是工厂方法模式的类图。

  首先我们有两个产品ProductP1和ProductP2,我们现在要生产这两个产品,这两个产品特征如下:

  (1) start(); 启动

  (2) execute(); 运行

  (3) quit(); 退出

  只是启动过程不同,运行过程不同,退出也不同。

那么工厂方法模式是如何实现得到这两个产品的对象的呢??通过上面的类图其实我们就可以大概知道了,工厂方法大致实现过程。有几个产品,就对应着有几个工厂,每个工厂负责生产对应的产品。所有工厂都实现了同一个工厂接口Creator。而所有的产品也都实现了同一个产品的接口Product。

  • Product(定义工厂方法所创建的对象的接口,也就是产品的接口)
    • class Product{Product(){};~Product(){};virtual void start()=0;virtual void execute()=0;virtual void quit()=0;
      };
  • ConcreteProduct(实现Product接口,也就是每个产品具体的实现方法,这里有两个产品ConcreteProductP1和ConcreteProductP2)
    • /**************************产品1*******************************/
      class
      ConcreteProductP1:public Product{ConcreteProductP1(){};~ConcreteProductP1(){};void start();void execute();void quit(); }; ConcreteProductP1::start(){cout<<"<<----------P1 启动---------->>"<<endl; } ConcreteProductP1::execute(){cout<<"<<----------P1 执行---------->>"<<endl; } ConcreteProductP1::quit(){cout<<"<<----------P1 退出---------->>"<<endl; } /*************************产品2********************************/ class ConcreteProductP2:public Product{ConcreteProductP2(){};~ConcreteProductP2(){};void start();void execute();void quit(); }; ConcreteProductP2::start(){cout<<"<<----------P2 启动---------->>"<<endl; } ConcreteProductP2::execute(){cout<<"<<----------P2 执行---------->>"<<endl; } ConcreteProductP2::quit(){cout<<"<<----------P2 退出---------->>"<<endl; }
  • Creator(声明工厂方法,该方法返回一个Product类型的对象;Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct对象,可以调用工厂方法以创建一个Product对象)

    class Creator{
    public:Creator(){};~Creator(){};virtual Product* createProduct()=0;
    };

     

  • ConcreteCreator(重定义工厂方法以返回一个ConcreteProduct实例,这里有两个工厂实现类,各自对应上面的两个产品)
    • /*************************工厂1生成产品1**************************/
      class ConcreteCreatorP1:public Creator{
      public:ConcreteCreatorP1(){};~ConcreteCreatorP1(){};Product* createProduct();
      };
      Product* ConcreteCreatorP1::createProduct(){return new ConcreteProductP1();
      }/*************************工厂2生成产品2**************************/
      class ConcreteCreatorP2:public Creator{
      public:ConcreteCreatorP2(){};~ConcreteCreator()P2{};Product* createProduct();
      };
      Product* ConcreteCreatorP2::createProduct(){return new ConcreteProductP2();
      }
  • Client (这里使用的是main函数)
  • int main(){Creator *factory = new ConcreteCreatorP1();Product *p1 = factory.createProduct();p1.start();        //p1是这样启动的p1.execute();    //p1是这样运行的p1.quit();        //p1是这样结束的
        Creator *factory = new ConcreteCreatorP2();Product *p2 = factory.createProduct();p2.start();        //p2是这样启动的p2.execute();     //p2是这样运行的p2.quit();         //p2是这样结束的return 0;
    }

  工厂方法很简单,经常作为一种标准的创建对象的方法。但是缺点就是可能仅仅是为了改变产品类,就可能需要创建一个新的类,也就是说当被实例化的类根本不发生变化或当实例化出现在子类可以很容易重定义的操作中,重新创建一个工厂类就显得太浪费了。

版权所有,欢迎转载,转载请注明出处。

转载于:https://www.cnblogs.com/whc-uestc/p/4750948.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/358364.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上架Android应用到腾讯应用包、百度手机助手、华为应用市场、小米应用商店、阿里应用分发平台需要准备哪些材料?...

前端时间用敏捷式开发平台开发了一款APP应用&#xff0c;应用名称我就不说啦&#xff0c;这篇文章主要讲述一下上架各大安卓应用商店&#xff08;腾讯应用宝、阿里应用商店、百度手机助手、华为应用市场、小米应用商店&#xff09;需要准备哪些材料&#xff0c;有相关的困扰欢迎…

【APICloud系列|18】上架Android应用到腾讯应用包、百度手机助手、华为应用市场、小米应用商店、阿里应用分发平台需要准备哪些材料?

前端时间用敏捷式开发平台开发了一款APP应用,应用名称我就不说啦,这篇文章主要讲述一下上架各大安卓应用商店(腾讯应用宝、阿里应用商店、百度手机助手、华为应用市场、小米应用商店)需要准备哪些材料,有相关的困扰欢迎私信我。 一、应用商店选择 推荐平台(六选五) 1.…

Activiti 6中的可插拔持久性

在过去的几年中&#xff0c;我们经常听到&#xff08;来自社区和我们的客户&#xff09;关于如何将Activiti的持久性逻辑从关系数据库交换到其他内容的请求。 当我们宣布Activiti 6时&#xff0c; 我们做出的承诺之一就是我们将实现这一目标。 深入研究Activiti引擎代码的人会…

src漏洞类型总结

本文转载于https://blog.csdn.net/qq_33942040/article/details/111831536 这三类存在漏洞可能更大 越他娘丑的站&#xff0c;越有可能存在洞。 Asp aspx 存在漏洞的可能更大 登陆口没得验证码的可能存在一,未授权访问 常见28种服务器或者中间协议未授权访问 易出现处 ①照片…

【APICloud系列|19】上架APPStore需要准备哪些材料?

前端时间用敏捷式开发平台开发了一款APP应用,应用名称我就不说啦,这篇文章主要讲述一下上架苹果应用商店APPStore需要准备哪些材料,有相关的困扰欢迎私信我。 一、上架流程 1. 注册苹果企业账号 2. 创建测试证书,发布证书 (使用Mac) 3. 使用xcode 上传应用到APP Store (…

Json注入

一、Json简介 JSON 是存储和交换文本信息的语法&#xff0c;是轻量级的文本数据交换格式。类似xml&#xff0c;但JSON 比 XML 更小、更快&#xff0c;更易解析。所以现在接口数据传输都采用json方式进行。JSON 文本的 MIME 类型是 “application/json”。 json语法 数据在名…

国行 lg g3 D858 刷 lg g3 D858hk 教程(备忘)

纯手打&#xff0c;转载请注明出处~ 刷机有风险&#xff0c;出现问题概不负责&#xff01; 本着自娱自乐的宗旨 &#xff0c;分享一下&#xff0c;出了问题不负责&#xff01; 准备的材料&#xff1a; 1&#xff0c;手机一枚&#xff08;废话&#xff09;国行lg g3 d858 2&am…

渗透测试-验证码的爆破与绕过

【验证码机制原理】 客户端发起请求->服务端响应并创建一个新的SessionID同时生成随机验证码&#xff0c;将验证码和SessionID一并返回给客户端->客户端提交验证码连同SessionID给服务端->服务端验证验证码同时销毁当前会话&#xff0c;返回给客户端结果。 【客户端可…

最近对项目代码做的一些更改和感想

最近对项目代码做了一些更改&#xff0c;主要的改动是对整个界面框架的改变&#xff0c;因为以前写代码的时候&#xff0c;为了完成功能&#xff0c;没有从上帝视角来思考软件的界面设计&#xff0c;完全是需要这个功能了&#xff0c;怎么可以做到&#xff1f;好&#xff0c;就…

CSS常见的四种垂直居中的方法

面试中不管是笔试题还是面试题,一般很容易被问到如何实现垂直水平居中,这里总结四种方法作为参考 (1)margin:auto法 css: div{ width: 400px; height: 400px; position: relative; border: 1px solid #465468; } img{ position: absolute; margin: auto; top: 0; left: 0; …

对安卓应用进行加固签名,为上架各大应用市场做准备

上架安卓各大应用市场之前需要对自己的应用进行签名加固&#xff0c;签名是为了证明你是这个应用的开发者&#xff0c;软著也是一种方式&#xff0c;这是不做介绍&#xff0c;加固是为了从安全角度给安装包加一个保护层&#xff0c;防止被恶意破解及攻击。下面简单介绍一下签名…

大前端最强vscode教程(基础篇)

这段时间入职了一家外包公司的前端工程师岗位,前端编辑器用起来,前端一般会用到几个编译器,VScode、sublime text3、webstorm、Hbuid等,这里主要介绍VScode. 初次使用vscode时各种不适应,所有需要用到的功能貌似都需要单独安装插件才能用。这让很多初次使用vscode的朋友有…

edusrc0day挖掘技巧

网瑞达web资源管理系统0day ps&#xff1a; 作为在edusrc的小白&#xff0c;经常看见大师傅们的刷屏&#xff0c;我也很向往能像大师们一样有一次刷屏的机会&#xff0c;于是有了这一次的渗透之旅。 思路&#xff1a;要想刷屏上分&#xff0c;就得找系统来挖掘&#xff0c;对…

个人或者公司如何写版权认证的证明文件?

项目场景&#xff1a; 现在好多平台都在做知识付费&#xff0c;比如百度文库、CSDN、微博、头条、知乎等等&#xff0c;因此我想给大家做一些付费文档&#xff0c;想上传到百度文库的知识店铺 问题描述&#xff1a; 一般人不知道这个版权认证文件怎么写&#xff0c;怎么弄&am…

Bypass WAF实战总结

0X00前言 上个月刷了一波洞&#xff0c;然后这个月初远程支持了一个HW&#xff0c;在文件上传getshell的时候&#xff0c;碰到个各式各样的云waf&#xff0c;通过一个月的实战&#xff0c;总结了几个比较实用的技巧&#xff0c;文章总结的不全&#xff0c;只是基于我实战中用到…

Git教程学习总结(分享给热爱学习的你,团队的协作离不开你呀)

目录 Git 教程 Git 安装配置 Git 工作流程 Git 工作区、暂存区和版本库 Git 创建仓库 Git 基本操作 Git 分支管理 Git 查看提交历史 git log git blame Git 标签 Git 远程仓库(Github) Git Gitee Git 服务器搭建 Git 教程 Git 是一个开源的分布式版本控制系统&…

Linux的shell编写

-eq //等于 -ne //不等于 -gt //大于 -lt //小于 ge //大于等于 le //小于等于实验中遇到的问题&#xff1a; 1.NAMEuser1 中间不能有空格 2.[ xxx ] xxx前面和后面要有空格 任务1&#xff1a;使用case语句编…

为啥这么多程序员大佬学习Cortex-M3

Cortex-M3是一个32位处理器内核。内部的数据路径是32位的&#xff0c;寄存器是32位的&#xff0c;存储器接口也是32位的。CM3采用了哈佛结构&#xff0c;拥有独立的指令总线和数据总线&#xff0c;可以让取指与数据访问并行不悖。这样一来数据访问不再占用指令总线&#xff0c;…

Ffuf使用教程

kali安装教程链接&#xff1a;https://www.iculture.cc/cybersecurity/pig210 该工具用途广泛&#xff0c;可用于多种用途。一些用途&#xff1a; • 目录发现&#xff0c;可选择在 URL 中的任何位置进行模糊测试。 • 子域名发现 • 使用各种 HTTP 方法进行模糊测试。 安装 …

Burp Collaborator 使用总结

0x00&#xff1a;使用原因 我们在做渗透测试的时候&#xff0c;经常会遇到这种情况&#xff0c;测试跨站可能有些功能插入恶意脚本后无法立即触发&#xff0c;例如提交反馈表单&#xff0c;需要等管理员打开查看提交信息时才会触发&#xff0c;或者是盲注跨站&#xff0c;盲打 …