浅谈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;有相关的困扰欢迎…

java并发队列_Java并发教程–阻塞队列

java并发队列如第3部分所述&#xff0c;Java 1.5中引入的线程池提供了核心支持&#xff0c;该支持很快成为许多Java开发人员的最爱。 在内部&#xff0c;这些实现巧妙地利用了Java 1.5中引入的另一种并发功能-阻塞队列。 队列 首先&#xff0c;简要回顾一下什么是标准队列。 …

BBScan:信息泄漏批量扫描脚本

有些朋友手上有几十万甚至上百万个域名&#xff0c;如果把这些域名全部扔给wvs、 APPscan这样的重型扫描器&#xff0c;显然是不太合适的。 对于一个拥有上万IP的企业&#xff0c;又如何快速定位可能存在弱点的机器呢&#xff1f; 试试信息泄漏批量扫描脚本 BBScan。 BBScan是一…

【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种服务器或者中间协议未授权访问 易出现处 ①照片…

[LeetCode][JavaScript]Roman to Integer

Roman to Integer Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999. https://leetcode.com/problems/roman-to-integer/ 罗马数字转阿拉伯数字。 从后往前扫&#xff0c;如果当前的数大于之前的数&#xff0c;加…

【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…

七夕(情人节)表白女朋友,程序员应该如何装一波13

很多小伙伴私信说程序员应该怎么表白女朋友,大神支个招,直接上代码。最近的.vbs或者.vbe表白真的很火,小伙伴们赶紧动起来。(废话少说,赶紧往下看) 代码一: msgbox("做我女粉丝好吗?")msgbox("房产证上写你名字")msgbox("孙叫兽")msgb…

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

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

java并发调用_Java并发教程–可调用,将来

java并发调用从Java的第一个发行版开始&#xff0c;Java的美丽之处之一就是我们可以轻松编写多线程程序并将异步处理引入我们的设计中。 Thread类和Runnable接口与Java的内存管理模型结合在一起&#xff0c;意味着可以直接进行线程编程。 但是&#xff0c;如第3部分所述&#x…

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

最近对项目代码做了一些更改&#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; …

Linux下切换Python2和Python3的4种方法

本篇博文面向Linux用户&#xff0c;在Linux下(Ubuntu)下测试通过&#xff0c;Win用户嘛&#xff0c;…… 0x00 为什么需要有两个版本的Python Python2和Python3不兼容是每个接触过Python的开发者都知道的事&#xff0c;虽说Python3是未来&#xff0c;但是仍然有很多项目采用P…

异步EJB只是一个Gi头吗?

在之前的文章&#xff08; 此处和此处 &#xff09;中&#xff0c;我展示了当服务器负载沉重时&#xff0c;创建非阻塞异步应用程序可以提高性能。 EJB 3.1引入了Asynchronous批注&#xff0c;用于指定方法将在将来的某个时间返回其结果。 Javadocs声明必须返回void或Future 。…

常见的清除浮动的五种解决办法

方法一:使用带clear属性的空元素 在浮动元素后使用一个空元素如 <div class="clear"></div> 并在CSS中赋予 .clear{clear:both;} 属性即可清理浮动。亦可使用 <br class="clear" /> 或 <hr class="clear" /> …

Kali环境下安装python3

Kali环境下安装python3 参考&#xff1a; 由于kali环境下是自动安装了python 2.7&#xff0c;没有python3以上的版本&#xff0c;现在开始安装python 1. 先下载python3的tar包 进入这个目录&#xff1a; cd /usr/local/ 创建一个新文件夹python3&#xff1a; mkdir /usr/loc…

用汇编语言写的第一个DOS程序

今天整理电脑时&#xff0c;看到两三年前学习汇编语言时写的显示“Hello”的程序。不禁感叹那个时候学得如此用心&#xff0c;同样的功能&#xff0c;我竟然用了四种写法。现贴出源码&#xff0c;为了以后继续学习&#xff0c;也为了给初学者一点启发。(删掉注释了&#xff0c;…