工厂模式(简单工厂、工厂方法、抽象工厂)

简单工厂模式

      从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。 

简单工厂模式的一般结构,如图所示:

上门2个图片有对简单工厂模式的理解,来源《java与模式》

 

使用场景

 

工厂类负责创建的对象比较少。

客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

 

l 工厂角色

l 抽象产品角色

l 具体产品角色

   其实角色这个词用的比较确切,能够让我们理解到,每个角色的不是单纯地指一个类,可能是一组类所构成了这个角色。下面对三个角色进行描述:

1. 工厂角色

  工厂角色负责产品的生产工作。在简单工厂模式中,工厂类是一个具体的实现类,在系统设计中工厂类负责实际对象的创建工作。

  工厂类(Factory)的特点是:它知道系统中都存在哪些能够创建对象的具体类(ConcreteProduct),也知道该如何将创建的对象,以某种能够屏蔽具体类实现细节的方式(AbstractProduct)提供给所需要的其他角色来使用该对象提供的数据和服务。

2.抽象产品角色

  抽象产品角色是具体的产品的抽象。抽象就是将产品的共性抽取出来,可以直接暴露给客户端(需要使用具体产品的角色),对所有的客户端来说,从工厂中直接获取到的原始产品的外部形态都是相同的,没有任何的差别,包括数据和服务。这也就是说,具体客户端应该“秘密”掌握着某一个或一些具体产品的详细资料(具体产品类型、数据和服务),然后根据具体客户端(任何一个需要使用某种具体产品的数据和服务的实现类)需要什么样的附加数据和服务,进行类类型转换后,通过借助于对应的具体产品对象来完成其职责。

  抽象产品角色,在实际系统中可以定义为接口或者抽象类。

3.具体产品角色

  具体产品实现类一定是抽象产品类的实现或扩展。为了保证工厂类能够创建对象,工厂类需要知道具体产品的创建方式,这就涉及到具体产品类所提供的构造方法,以便,可能工厂类会向客户端提供具体创建服务所需要的数据。例如:某个产品类需要通过一个账号才能构造其实例,所以工厂类必须根据它的创建需求,为客户端提供一个带账号参数的生产方法,才能创建该具体产品类的对象。

  也就是说,工厂类依赖于具体产品实现类。同样,客户端类是依赖于工厂类的。

通过上述三个角色的描述,我们应该能够了解,系统中哪些类能够胜任上述的三个角色,并通过各类之间的关系,通过工厂模式来实现系统或者某个模块。在实际的设计过程中,可能不存在完全与上述基本简单工厂模式完全适应的,需要根据具体的需求来调整简单工厂模式的应用。只要能够实现系统的良好设计,有时候变化才能满足需要。

下面用一个简单的例子来说明一下,给大家加深一下印象(例子来自于网络):

运动员.java
public interface 运动员 {       public void 跑();public void 跳();
}
足球运动员.java
public class 足球运动员 implements 运动员 {public void 跑(){//跑啊跑} public void 跳(){//跳啊跳}
}
篮球运动员.java
public class 篮球运动员 implements 运动员 {public void 跑(){//do nothing}     public void 跳(){//do nothing}
}
体育协会.java
public class 体育协会 {   public static 运动员 注册足球运动员(){return new 足球运动员();}     public static 运动员 注册篮球运动员(){return new 篮球运动员();}
}俱乐部.java
public class 俱乐部 {private 运动员 守门员;private 运动员 后卫;private 运动员 前锋;public void test() {this.前锋 = 体育协会.注册足球运动员();this.后卫 = 体育协会.注册足球运动员();this.守门员 = 体育协会.注册足球运动员();守门员.跑();后卫.跳();}
}

以上就是简单工厂模式的一个简单实例,读者应该想象不用接口不用工厂而把具体类暴露给客户端的那种混乱情形吧(就好像没了体育总局,各个俱乐部在市场上自己胡乱的寻找仔细需要的运动员),简单工厂就解决了这种混乱。

工厂方法模式

工厂方法模式是类的创建模式,又叫虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。 工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际工作推迟到子类中。

工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。工厂方法模式的对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。 

工厂方法模式角色与结构

1.抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。  

2.具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。

3.抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。

4.具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。

工厂方法模式的一般结构,如图所示:

我们在不改变产品类(“足球运动员”类和“篮球运动员”类)的情况下,写一下工厂方法模式的例子:

 

运动员.java
public interface 运动员 {       public void 跑();public void 跳();
}足球运动员.java
public class 足球运动员 implements 运动员 {public void 跑(){//跑啊跑}public void 跳(){//跳啊跳}
}篮球运动员.java
public class 篮球运动员 implements 运动员 {public void 跑(){//do nothing}public void 跳(){//do nothing}
}体育协会.java
public interface 体育协会 {public 运动员 注册();
}足球协会.java
public class 足球协会 implements 体育协会 {public 运动员 注册(){return new 足球运动员();}
}篮球协会.java
public class 篮球协会 implements 体育协会 {public 运动员 注册(){return new 篮球运动员();}
}俱乐部.java
public class 俱乐部 {private 运动员 守门员;private 运动员 后卫;private 运动员 前锋;public void test() {体育协会 中国足协 = new 足球协会();this.前锋 = 中国足协.注册();this.后卫 = 中国足协.注册();守门员.跑();后卫.跳();}
}

 

很明显可以看到,“体育协会”工厂类变成了“体育协会”接口,而实现此接口的分别是“足球协会”“篮球协会”等等具体的工厂类。
这样做有什么好处呢?很明显,这样做就完全OCP了。如果需要再加入(或扩展)产品类(比如加多个“乒乓球运动员”)的话就不再需要修改工厂类了,而只需相应的再添加一个实现了工厂接口(“体育协会”接口)的具体工厂类。

抽象工厂模式

       抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据LSP原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。

     先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。还是让我们用一个例子来形象地说明一下吧。

抽象工厂模式中的有以下的四种角色:

抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。 

具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。

 抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。

具体产品(Concrete Product)角色:这个角色用以代表具体的产品。

 Abstract Factory模式的结构:

 

 

 

 

 

 package abstractFactory;public interface KitchenFactory{public Food getFood();public TableWare getTableWare();}抽象餐具的接口定义如下所示:package abstractFactory;public interface TableWare{public String getTool();}抽象事物的接口定义如下所示:package abstractFactory;public interface Food{public String getEatable();}而具体的实现也非常简单,以AKitchen为例子具体工厂AKitchen的定义如下所示;package abstractFactory;public class AKitchenimplements KitchenFactory{public Food getFood(){return new Milk();}public TableWare getTableWare(){return new Spoon();}}具体餐具(spoon)的定义如下所示:package abstractFactory;public class Spoonimplements TableWare{ public String getTool() {return "spoon";}}具体食物(milk)的定义如下所示:package abstractFactory;public class Milkimplements Food{public String getEatable(){return "milk";}}客户端的定义如下:package abstractFactory;public class Client{public void eat(KitchenFactory k){System.out.println("A person eat "+k.getFood().getEatable()+" with "+k.getTableWare().getTool()+"!");}public static void main(String[] args){Client client=new Client();KitchenFactory kf =new AKitchen();client.eat(kf);kf=new BKitchen();client.eat(kf);kf=new CKitchen();client.eat(kf);}}

 

在以下情况下应当考虑使用抽象工厂模式:

· 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。

· 这个系统有多于一个的产品族,而系统只消费其中某一产品族。

· 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。

· 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

 

 

 

 

 

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

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

相关文章

设置 Xcode 自动生成代码片段

一、什么是代码片段当在Xcode中输入dowhile并回车后,Xcode会出现下图所示的提示代码:这就是代码片段,目的是使程序员以最快的速度输入常用的代码片段,提高编程效率。该功能是从Xcode4开始引入的。在Xcode中的位置如下图所示&#…

C# 10 新特性 —— CallerArgumentExpression

C# 10 新特性 —— CallerArgumentExpressionIntroC# 10 支持使用 CallerArgumentExpression 来自动地获取调用方的信息,这可以简化我们现在的一些代码,让代码更加简洁,一起看下面的示例吧Caller InfoC# 在 5.0 的时候开始支持 Caller Info 自…

一款不错的编程字体Source Code Pro

我以前一直是用的MS自家的是Consolas的字体,这个字体基本上具有编程字体所需的所有要素:等宽、支持ClearType、中文字体大小合适,l和1,o和0很容易区分。非要挑刺的话就是字体比较小,9号和10号字区别不大,长…

当代年轻人熬夜晚睡的原因找到了!

全世界只有3.14 % 的人关注了爆炸吧知识有人熬夜为了离梦想更近有人熬夜为了给自家爱豆做数据有人熬夜只是因为深夜才有点自己的时间还有人是因为“沉迷”这些优质视频号忘记要睡在过去一段时间里,视频号可能是微信迭代最多,变化最多,也受到最…

怎么安装SharePoint2013 preview 在SQL2012 和 Windows Server 2008 R2 SP1

微软上周发布了其支柱产品Office2013 和SharePoint2013 preview. 对于以SharePoint 吃饭的人当然是很兴奋。今天我在这里演示一下怎么安装SharePoint2013 preview 在SQL2012 和 Windows Server 2008 R2 SP1 。 1.需要在你的Active Directory(AD)里建一个用户 ,我把它…

Mac 登陆 去掉 其他用户

2019独角兽企业重金招聘Python工程师标准>>> 打开 终端 sudo defaults write /Library/Preferences/com.apple.loginwindow SHOWOTHERUSERS_MANAGED -bool FALSE 转载于:https://my.oschina.net/liuchuanfeng/blog/617387

使用 Windbg 分析一个 异步操作 引发的 Crash 异常

上周我们收到了一个客户的紧急求助,他们的一个 iis应用程序池 经历了频繁重启,即使从错误日志中也不得到任何有用的信息,异常信息如下:System.NullReferenceException : Object reference not set to an instance of an object. S…

wxGlade的图标,原来是来自蒙德里安的名画!

一直用wxGlade做GUI的,今天突然发现它的图标和一副油画很像。 wxGlade的图标,图标的文件名竟然就叫做mondrian.ico 蒙德里安创造了很多这种纯粹的基本要素的作品,下面是其中之一,《构图》(Composition 1929 - Piet Mon…

SAP HANA解读-2012 SAP商业同略会分享

7月26日和27日,我受邀参加了SAP在国家会议中心举办的“蕴韬略促转变共发展”为主题的中国商业同略会,下面就参会的一些感想和大家分享一下。 SAP中国商业同略会是第二次在北京举办,此次大会汇聚国内外知名商业领袖、企业高层、行业权威、专家…

java日期加减秒_Java日期——年、月、日、时、分、秒、周加减计算

Java日期——年、月、日、时、分、秒、周加减计算Java日期——年、月、日、时、分、秒、周加减计算1.Pom依赖joda-timejoda-time2.9.92.示例代码package com.example.demo.controller;import org.joda.time.DateTime;import java.text.SimpleDateFormat;import java.util.Date;…

不可思议!这篇全篇脏话的文章竟然发表了

全世界只有3.14 % 的人关注了爆炸吧知识一教授为了抗议三流科学杂志发送垃圾邮件,回复了一篇全文只重复七个脏话字眼的论文,竟被出版!这是十几年前,麻省理工大学的一个教授埃迪科勒,发表的一篇名为 Get me off Your Fu…

设置圆角、定向设置圆角-按钮等控件

为什么80%的码农都做不了架构师?>>> //定向设置圆角UIBezierPath *maskPath [UIBezierPath bezierPathWithRoundedRect:whiteView.bounds byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(10, 10)];CASha…

C# 10 新特性 —— Lambda 优化

C# 10 新特性 —— Lambda 优化IntroC# 10 对于 Lambda 做了很多的优化,我们可以在 C# 中更加方便地使用委托和 Lambda 了,下面就来看一些示例Lambda EnhancementsNatural types for lambdasC# 10 可以更好做类型推断,很多时候编译器可以自动…

40个最好的Tumblr主题

如果安装了一款较好的Tumblr主题,你的Tumblr空间将焕然一新。然而找到一款合适的主题并不是一件容易的事,这正是本文中我整理那么多优质的Tumblr模板作为灵感的原因。其中有一些免费的Tumblr主题,另外的一些付费的Tumblr主题也确实很棒&#…

现代女性都有哪些烦恼?

1 医生,咱可以先拔下来么!▼2 靓仔,我笑得停不下来!(via.豆瓣哈组)▼3 边做饭边把锅给洗了(素材来源网络,侵删)▼4 令人无路可退的辞职方式!?&…

c++11新特性(4) lambda捕捉块

lambda表达式中的方括号成为捕捉块,能够在这里指定怎样从所在的作用域中捕捉变量. 捕捉的意思是指能够在该lambda中使用该变量.即能够捕获外部变量在lambda表达式内使用. 能够使用两种方式来捕捉所在的作用域中的全部变量. []:通过值捕捉全部变量 [&]:通过引用捕捉全部变量…

别不承认!搞懂那些数理原理,才发现它们和枯燥根本不沾边!

▲ 点击查看数理化的学习对于很多孩子,包括家长都是一个大难题。比如,我们要教孩子认识动物,一般是要给孩子看动物的图片或实体,孩子自然就对这个动物有个认知。要教孩子数字,就会用一件玩具、两个苹果这种和现实有关联…

WPF实现数据拾取器

WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织由于在WPF中没有现成的数据拾取器控件,所以我们自己实现一个。PS:有更好的方式欢迎推荐。01—代码如下一、创建 RoundPicker.cs 继承 Control代码如下。RoundPicker.cs实现…

CAS的安装与配置(一)服务器端配置

一、搭建Java Web服务器环境 CATALINA_HOME D:\Java\apache-tomcat-6.0.14 安装完毕,启动Tomcat ,在浏览器上 测试 http://localhost:8080/ 出现上述界面,表明系统成功搭建。 二、使用Java Keytool工具为系统生成HTTPS证书,并…

某大型银行深化系统之十六:性能设计之一

传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 1队列服务质量评估 通过引入排队系统,定义系统中各项业务流程的产生和业务服务模型,描述工作项产生规律和服务规律的概率来计算系统的性能。 在对排队进行分析时,…