设计模式--抽象工厂(个人笔记)

一、抽象工厂的应用场景以及优缺点

1  应用场景:

      如果系统需要多套的代码解决方案,并且每套的代码解决方案中又有很多相互关联的产品类型,并且在系统中我们可以相互替换的使用一套产品的时候可以使用该模式,客户端不需要依赖具体的实现。

2 优点:

      抽象工厂模式将产品的创建工作迟到了具体工厂的子类中,我们声明工厂类变量的时候是使用的抽象类型,同理,我们使用产品类型也是抽象类型。

      这样做就尽可能的减少了客户端代码与产品类之间的依赖,从而降低了系统的耦合度。耦合度降低了,对于后期的维护和扩展就更加的有利。

3 缺点:

      抽象工厂模式很难支持增加新产品的变化,这是因为抽象工厂接口中已经明确了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,

      这样就涉及到抽象工厂类的以及所有子类的变化。也就违背了“开放--封闭”原则。

4.实现要点:

       1)、如果没有应对“多系列对象创建”的需求变化,则没有必要使用AbstractFactory模式,这时候使用简单的静态工厂完全可以。

       2)、"系列对象"指的是这些对象之间有相互依赖、或作用的关系,例如游戏开发场景中“道路”与“房屋”的依赖,“道路”与“地道”的依赖。

       3)、AbstractFactory模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动。

       4)、AbstractFactory模式经常和FactoryMethod模式共同组合来应对“对象创建”的需求变化。

二、模式的组成

1 抽象产品类角色(AbstractProduct):

       为抽象工厂中相互依赖的每种产品定义抽象接口对象,

       也可以这样说,有几种产品,就要声明几个抽象角色, 每一个抽象角色和一种具体的产品相匹配。

2 具体产品类(ConcreteProduct):

       具体产品类实现了抽象产品类,是针对某个具体产品的实现的类型。

3  抽象工厂类角色(AbstractFactory):

        定义了创建一组相互依赖的产品对象的接口操作,每种操作和每种产品一一对应。

4  具体工厂类角色(ConcreteFactory):

        实现抽象类里面的所有抽象接口操作,可以创建某系列具体的产品,这些具体的产品是“抽象产品类角色”的子类。

三、代码

  1.基本代码:

 #region 创建抽象类/// <summary>/// 房顶抽象类,子类的房顶必须继承该类/// </summary>public abstract class Roof{/// <summary>/// 创建房顶/// </summary>public abstract void Create();}/// <summary>/// 地板抽象类,子类的地板必须继承该类/// </summary>public abstract class Floor{/// <summary>/// 创建地板/// </summary>public abstract void Create();}/// <summary>/// 窗户抽象类,子类的窗户必须继承该类/// </summary>public abstract class Window{/// <summary>/// 创建窗户/// </summary>public abstract void Create();}/// <summary>/// 房门抽象类,子类的房门必须继承该类/// </summary>public abstract class Door{/// <summary>/// 创建房门/// </summary>public abstract void Create();}/// <summary>/// 桌子抽象类,子类的房门必须继承该类/// </summary>public abstract class Dask{/// <summary>/// 创建桌子/// </summary>public abstract void Create();}#endregion 创建抽象类#region 实现具体类/// <summary>/// 欧式地板类/// </summary>public class EuropeanFloor : Floor{public override void Create(){Console.WriteLine("创建欧式的地板");}}/// <summary>/// 欧式的房顶/// </summary>public class EuropeanRoof : Roof{public override void Create(){Console.WriteLine("创建欧式的房顶");}}/// <summary>///欧式的窗户/// </summary>public class EuropeanWindow : Window{public override void Create(){Console.WriteLine("创建欧式的窗户");}}/// <summary>/// 欧式的房门/// </summary>public class EuropeanDoor : Door{public override void Create(){Console.WriteLine("创建欧式的房门");}}/// <summary>/// 欧式桌子类/// </summary>public class EuropeanDask : Dask{public override void Create(){Console.WriteLine("创建欧式的桌子");}}/// <summary>/// 现代的房顶/// </summary>public class ModernizationRoof : Roof{public override void Create(){Console.WriteLine("创建现代的房顶");}}/// <summary>/// 现代的地板/// </summary>public class ModernizationFloor : Floor{public override void Create(){Console.WriteLine("创建现代的地板");}}/// <summary>/// 现代的窗户/// </summary>public class ModernizationWindow : Window{public override void Create(){Console.WriteLine("创建现代的窗户");}}/// <summary>/// 现代的房门/// </summary>public class ModernizationDoor : Door{public override void Create(){Console.WriteLine("创建现代的房门");}}/// <summary>/// 现代的桌子(扩展)/// </summary>public class ModernizationDask : Dask{public override void Create(){Console.WriteLine("创建现代的桌子");}}#endregion 实现具体类#region 创建抽象工厂类/// <summary>/// 抽象工厂类,提供创建不同类型房子的接口/// </summary>public abstract class AbstractFactory{// 抽象工厂提供创建一系列产品的接口,这里作为例子,只给出了房顶、地板、窗户和房门创建接口public abstract Roof CreateRoof(); //(可多可单)public abstract Floor CreateFloor();public abstract Window CreateWindow();public abstract Door CreateDoor();public abstract Dask CreateDask();//(扩展)}#endregion#region 实现抽象工厂类/// <summary>/// 欧式风格房子的工厂,负责创建欧式风格的房子/// </summary>public class EuropeanFactory : AbstractFactory{// 制作欧式房顶public override Roof CreateRoof(){return new EuropeanRoof();}// 制作欧式地板public override Floor CreateFloor(){return new EuropeanFloor();}// 制作欧式窗户public override Window CreateWindow(){return new EuropeanWindow();}// 制作欧式房门public override Door CreateDoor(){return new EuropeanDoor();}// 制作欧式桌子(扩展)public override Dask CreateDask(){return new EuropeanDask();}}/// <summary>/// 现在风格房子的工厂,负责创建现代风格的房子/// </summary>public class ModernizationFactory : AbstractFactory{// 制作现代房顶public override Roof CreateRoof(){return new ModernizationRoof();}// 制作现代地板public override Floor CreateFloor(){return new ModernizationFloor();}// 制作现代窗户public override Window CreateWindow(){return new ModernizationWindow();}// 制作现代房门public override Door CreateDoor(){return new ModernizationDoor();}// 制作现代桌子只有现代有)public override Dask CreateDask(){return new ModernizationDask();}}#endregion

 

  2.扩展代码:

   新建一套古典风格的房子:

 

/// <summary>///先为表弟的房子来建立一个工厂类吧/// </summary>public class ClassicalFactory : AbstractFactory{//创建房顶public override Roof CreateRoof(){return new  ClassicalRoof();}// 创建地板public override Floor CreateFloor(){return new  ClassicalFloor();}// 创建窗户public override Window CreateWindow(){return new  ClassicalWindow();}// 创建房门public override Door CreateDoor(){return new  ClassicalDoor();}}/// <summary>///古典的房顶/// </summary>public class  ClassicalRoof : Roof{public override void Create(){Console.WriteLine("创建古典的房顶");}}/// <summary>/// 古典的地板/// </summary>public class  ClassicalFloor : Floor{public override void Create(){Console.WriteLine("创建古典的地板");}}/// <summary>/// 古典的窗户/// </summary>public class  ClassicalWindow : Window{public override void Create(){Console.WriteLine("创建古典的窗户");}}/// <summary>/// 古典的房门/// </summary>public class  ClassicalDoor: Door{public override void Create(){Console.WriteLine("创建古典的房门");}}

  此时,只需要添加五个类:一个是古典风格工厂类,负责创建古典风格的房子,另外几个类是具有古典风格的房顶、地板、窗户和房门的具体产品。

       从上面代码看出,抽象工厂对于系列产品的变化支持 “开放——封闭”原则(指的是要求系统对扩展开放,对修改封  闭),扩展起来非常简便,

        但是,抽象工厂对于增加新产品这种情况就不支持”开放——封闭 “原则,因为要修改创建系列产品的抽象基类 AbstractFactory,增加相应产品的创建方法,这也是抽象工厂的缺点所在。

 

说明:此文章纯属个人笔记,加深记忆,希望以后能写出自己的作品。

 

转载于:https://www.cnblogs.com/BounceGuo/p/10180015.html

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

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

相关文章

利用阿里云OSS对文件进行存储,上传等操作

--pom.xml加入阿里OSS存储依赖 <!--阿里云OSS存储--> <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>2.8.3</version> </dependency> --配置阿里云oss相关常量参数 /…

Java并发编程之ThreadGroup

ThreadGroup是Java提供的一种对线程进行分组管理的手段&#xff0c;可以对所有线程以组为单位进行操作&#xff0c;如设置优先级、守护线程等。 线程组也有父子的概念&#xff0c;如下图&#xff1a; 线程组的创建 1 public class ThreadGroupCreator {2 3 public static v…

springboot 缓存ehcache的简单使用

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 步骤&#xff1a; 1. pom文件中加 maven jar包&#xff1a; <!-- ehcache 缓存 --><dependency><groupId>net.sf.eh…

Spring boot + mybatis plus 快速构建项目,生成基本业务操作代码。

---进行业务建表&#xff0c;这边根据个人业务分析&#xff0c;不具体操作 --加入mybatis plus pom依赖 <!-- mybatis-plus 3.0.5--> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId>&l…

给手机浏览器减负 轻装上阵才能速度制胜

随着手机浏览器的发展&#xff0c;浏览器已经变得臃肿不堪&#xff0c;各种“功能”系于一身&#xff0c;有广告、社区、乐园等等&#xff0c;我们真的需要它们吗&#xff1f;如何才能让浏览器做到轻装上阵&#xff0c;又能高效满足我们需求呢&#xff1f; 过多“功能”的浏览器…

653. Two Sum IV - Input is a BST

题目来源&#xff1a; 自我感觉难度/真实难度&#xff1a; 题意&#xff1a; 分析&#xff1a; 自己的代码&#xff1a; class Solution(object):def findTarget(self, root, k):""":type root: TreeNode:type k: int:rtype: bool"""Allself.InO…

解决 dubbo问题:Forbid consumer 192.xx.xx.1 access service com.xx.xx.xx.rpc.api.xx from registry 116.xx1

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我的情况是&#xff1a; 原本我把服务放在A工程中&#xff0c;后来改到B工程中了&#xff0c;所以原来的服务不存在了&#xff0c;查不…

vue学习:7、路由跳转

2019独角兽企业重金招聘Python工程师标准>>> <body><div id"app"></div></body><script type"text/javascript">var Login {template: <div>我是登陆界面</div>};var Register {template: <div…

Spring Retry 重试机制实现及原理

概要 Spring实现了一套重试机制&#xff0c;功能简单实用。Spring Retry是从Spring Batch独立出来的一个功能&#xff0c;已经广泛应用于Spring Batch,Spring Integration, Spring for Apache Hadoop等Spring项目。本文将讲述如何使用Spring Retry及其实现原理。 背景 重试&…

inline 内联函数详解 内联函数与宏定义的区别

一、在C&C中   一、inline 关键字用来定义一个类的内联函数&#xff0c;引入它的主要原因是用它替代C中表达式形式的宏定义。表达式形式的宏定义一例&#xff1a;#define ExpressionName(Var1,Var2) ((Var1)(Var2))*((Var1)-(Var2))为什么要取代这种形式呢&#xff0c;且…

Oracle序列更新为主键最大值

我们在使用 Oracle 数据库的时候&#xff0c;有时候会选择使用自增序列作为主键。但是在开发过程中往往会遇到一些不规范的操作&#xff0c;导致表的主键值不是使用序列插入的。这样在数据移植的时候就会出现各种各样的问题。当然数据库主键不使用序列是一种很好的方式&#xf…

dubbo forbid service的解决办法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 017-05-31 10:36:54.523 [http-nio-8080-exec-5] ERROR c.h.pdl.web.APIExceptionHandler - Unknown Exception, URI /payday-loan-co…

用SSH登录远程的机器,在远程机器上执行本地机器上的脚本

假设本地的机器IP为10.245.111.90&#xff0c;我们想要在10.245.111.93上执行一个保存在10.245.111.90上的脚本。经过测试通过的命令如下&#xff1a;ssh root10.245.111.93 bash -s < /root/testlocal.sh如果要带参数的话&#xff0c;那就需要参考这篇文章中描述的代码了。…

golang学习之旅(1)

这段时间我开始了golang语言学习&#xff0c;其实也是为了个人的职业发展的拓展和衍生&#xff0c;语言只是工具&#xff0c;但是每个语言由于各自的特点和优势&#xff0c;golang对于当前编程语言的环境&#xff0c;是相对比较新的语言&#xff0c;对于区块链&#xff0c;大数…

为什么要在Linux平台上学C语言?用Windows学C语言不好吗?

用Windows还真的是学不好C语言。C语言是一种面向底层的编程语言&#xff0c;要写好C程序&#xff0c;必须对操作系统的工作原理非常清楚&#xff0c;因为操作系统也是用C写的&#xff0c;我们用C写应用程序直接使用操作系统提供的接口&#xff0c;Linux是一种开源的操作系统&am…

数据库中Schema(模式)概念的理解

在学习SQL的过程中&#xff0c;会遇到一个让你迷糊的Schema的概念。实际上&#xff0c;schema就是数据库对象的集合&#xff0c;这个集合包含了各种对象如&#xff1a;表、视图、存储过程、索引等。为了区分不同的集合&#xff0c;就需要给不同的集合起不同的名字&#xff0c;默…

linux系统中打rz命令后出现waiting to receive.**B0100000023be50

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 linux系统中打rz命令后出现 waiting to receive.**B0100000023be50 而没有出现选择文件弹出框是什么问题&#xff1a; 我本来用的是 gi…

golang学习之旅(2)- go的数据基本数据类型及变量定义方式

叮铃铃&#xff0c;这不有人在评论问下一篇何时更新&#xff0c;这不就来了嘛&#xff0c;&#x1f604; 今天我们说说golang 的基本数据类型 基本类型如下&#xff1a; //基本类型 布尔类型&#xff1a;bool 即true 、flase 类似于java中的boolean 字符类型&#xff1a;s…

StackExchange.Redis 官方文档(六) PipelinesMultiplexers

流水线和复用 糟糕的时间浪费。现代的计算机以惊人的速度产生大量的数据&#xff0c;而且高速网络通道(通常在重要的服务器之间同时存在多个链路)提供了很高的带宽&#xff0c;但是计算机花费了大量的时间在 等待数据 上面&#xff0c;这也是造成使用持久性链接的编程方式越来越…

开发优秀产品的六大秘诀

摘要&#xff1a;本文是Totango的联合创始人兼公司CEO Guy Nirpaz发表在Mashable.com上的文章。无论是在哪个行业&#xff0c;用户永远是一款产品的中心&#xff0c;本文作者就以用户为中心&#xff0c;为大家讲述了六个如何为企业产品添加功能的秘诀。 随着云计算的发展&#…