技术标签: 模式/分析/管理 exception Java java 产品 shapes class 设计模式
FactoryMethod是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了.简单说来,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将Factory Method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化
图1是Factory Method 模式的结构图,这里提供了一些术语,让我们可以进行更方便的描述:
由此可以清楚的看出这样的平行对应关系: Product <====> Creator ; ConreteProduct <====> ConreteCreator
抽象产品对应抽象创建器,具体产品对应具体创建器.这样做的好处是什么呢?为什么我们不直接用具体的产品和具体的创建器完成需求呢?实际上我们也可以这样做.但通过Factory Method模式来完成,客户(client)只需引用抽象的Product和Creater,对具体的ConcreteProduct和ConcreteCreator可以毫不关心,这样做我们可以获得额外的好处:
现在,请再回头看看基本概念中的那段话,开始也许觉得生涩难懂,现在是不是已经明朗化了很多.
下面让我们看看在 Java 中如何实现Factory Method模式,进一步加深对它的认识.
先说明一点,用Factory Method模式创建对象并不一定会让我们的代码更短,实事上往往更长,我们也使用了更多的类,真正的目的在于这样可以灵活的,有弹性的创建不确定的对象.而且,代码的可重用性提高了,客户端的应用简化了,客户程序的代码会大大减少,变的更具可读性.
1.a 首先定义一个抽象类Shape,定义两个抽象的方法.
1.b 定义 Shape的两个子类: Circle, Square,实现Shape中定义的抽象方法
1.c 定义抽象的创建器,anOperation调用factoryMethod创建一个对象,并对该对象进行一系列操作.
1.d 定义与circle和square相对应的两个具体创建器CircleFactory,SquareFactory,实现父类的methodFactory方法
1.e 测试类:请注意这个客户端程序多么简洁,既没有罗嗦的条件判断语句,也无需关心ConcreteProduct和ConcreteCreator的细节(因为这里我用anOperation封装了Product里的两个方法,所以连Product的影子也没看见,当然把Product里方法的具体调用放到客户程序中也是不错的).
运行结果如下:
The current shape is: Shape one (created by SquareFactory)
It will draw a square.
It will erase a square.
The current shape is: Shape two (created by CircleFactory)
It will draw a circle.
It will erase a circle.
2.a 我们在第一种方法的基础上进行修改,首先自定义一个的异常,这样当传入不正确的参数时可以得到更明显的报错信息.
2.b去掉了ShapeFactory的两个子类,改为由ShapeFactory直接负责实例的创建. ShapeFactory自己变成一个具体的创建器,直接用参数化的方法实现factoryMethod返回多种对象.
2.c 测试类:这里客户端必须指定参数来决定具体创建哪个类.这个例子里的anOperation是静态函数,可以直接引用.
运行结果如下:
有的时候我们会把ConcreteProduct的实例传给创建器作为参数,这种情况下,如果在创建器里完成创建过程,就必须判断参数的具体类型(用instanceof),然后才能产生相应的实例,那么比较好的做法是利用Java的动态装载机制来完成这件事.比如:
我们得到一个Shape的子类s,但不知道具体是那个子类,就可以利用Class类自带的方法newInstance()得到实例
return (Shape)s.getClass().newInstance();
这种方法有兴趣得读者可以自己尝试,限于篇幅,不写具体代码出来了.
看完这篇文章后,相信读者对Factory Method模式有一个比较清楚的了解了.我想说的是,我们不仅应该关心一个具体的模式有什么作用,如何去实现这个模式,更应该透过现象看本质,不但知其然,还要知其所以然.要通过对模式的学习加深对面向对象思想的理解,让自己的认识得到升华.Factory Method模式看似简单,实则深刻.抽象,封装,继承,委托,多态,针对接口编程等面向对象中的概念都在这里得到了一一的体现.只有抓住了它的本质,我们才能够不拘于形式的灵活运用,而不是为了使用模式而使用模式.
|
刘湛,武汉大学信息与计算科学系学士,熟悉 Java 语言和 J2EE 思想,国内多个 Java 论坛版主,现致力于 J2EE 平台上的 eCRM 套件开发。你可以通过 [email protected]与他联系! |
文章浏览阅读69次。软件总存在这样或者那样的bug。虽然测试员已经在很努力的寻找问题,程序员也在汗流浃背的除虫,但是总会有一些情况被遗漏或者不可预测,比如用户的硬件环境、网络状况、操作系统差异等等,不一而足。而导致的结果则是弹出下面这样一个让用户摸不着头脑又恼火的提示,然后崩溃掉,令程序员尴尬不已。而在一些成熟的软件产品中,程序崩溃时我们看到的却是另外一番画面,比如QQ:又比如迅雷:..._mfc程序出现 appcrash
文章浏览阅读7.5k次,点赞2次,收藏34次。并行地形成各级进位,各进位之间不存在依赖关系,因而这种方式也称为先行进位、同时进位或跳跃进位。_四位串行进位加法器
文章浏览阅读7.6k次,点赞3次,收藏36次。1分钟了解一个测开小知识:selenium对元素进行操作(三):日期控件处理如果日期控件支持输入,可以直接使用send_keys,按照文本框录入时间。但是大多数日期控件,都是这种格式<input type="text" autocomplete="off" readonly="readonly" placeholder="选择日期" class="aty-input aty-input-hasicon">控件的html描述是这样婶的。可以看到readonly="r_selenium日期控件处理
文章浏览阅读2.2k次。我们公司说是小公司,老板说每年资金进场很大,说是大公司,来来回回,人的流动性挺高的。公司有从华为出来的"大牛",姑且称之为大牛吧,说要为了规范我们项目开发的流程和代码的质量,极力推荐使用软开云。本人也是一头雾水,因为野惯了,还真不习惯,找了不少资料,终于部署成功和拉取和上传代码了。工作里面的需求什么的略过...1.代码要上传,需要先建立一个仓库,点击下面的代码托管,再点击普通新建,为什..._软开云
文章浏览阅读7k次,点赞5次,收藏54次。1.网络介绍由通信介质将地理位置不同、相互独立的计算机连接起来,实现数据和资源共享。2.网络分类2.1 按照拓扑结构分类1.总线型(一根线上串好多计算机)特点:两端信号终结器,分叉处有T型头2.环形网络效率很低,同一时间只有两个计算机通信,这两台计算机有其自己的令牌。3.星形线路利用率虽然高,但是线路单一,一旦坏了就少了一条线路。且中央节点压力大。 单点护照网络利用率高,但是中央节点压力大。2.2 按照地域分类1.局域网一个公司、一个家庭2.城域网一个区、一个城市、一个国家_计算机网络基础知识点
文章浏览阅读5.9k次,点赞2次,收藏15次。前言: 2015年,整个超声技术界最引人注目的事情莫过于高通推出了超声波指纹识别技术Sense ID,而小米手机也成功搭载了这一项黑科技。自上世纪五十年代全国超声热之后,超声技术终于有机会成为大众话题之一超声检测技术基础之基础 绝大多数超声波的检测技术原理都基于pulse-echo——你在山谷里喊一声就是pulse, 被岩壁或者树反射回来的回声就是echo。 对于超声检测而言,特制的晶_超声指纹识别原理
文章浏览阅读177次。一直以来我们都是用Sentry做项目监控,不过前段时间我们的Sentry坏掉了(我搞坏的)但监控又是很有必要的,在sentry修好之前,我想先寻找一个临时的替代方案,同时发现网上关于ExceptionLess的资料少得可怜,ExceptionLess官方的文档也不是很完善,翻了好久文档和源码,于是有了本文……_vue2使用exceptionless
文章浏览阅读1.5k次。VS Code(Visual Studio Code)是一个由微软开发的免费的跨平台代码编辑器,可以在Windows、Linux和macOS上运行。它支持多种编程语言和文件格式,并具有许多功能和插件,可以增强编辑器的功能。VS Code具有内置的调试器、Git版本控制、智能代码完成、代码片段和扩展等功能,可以提高开发人员的生产力和代码质量。它也是一个开源项目,并且有一个活跃的社区来支持和扩展它的功能。最近我又增加了GitHub Copilot插件,编程爽得简直不要不要的。_为什么没人用vs写python
文章浏览阅读5.5k次,点赞2次,收藏17次。 对于交叉熵损失函数的来由有很多资料可以参考,这里就不再赘述。本文主要尝试对交叉熵损失函数的内部运算做深度解析。 1. 函数介绍 Pytorch官网中对交叉熵损失函数的介绍如下:CLASS torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=- 100,reduce=None, reduction=‘mean’, label_smoothing=0.0) 该损失函数计算输入和目标值之间的交叉熵损失。_crossentropyloss(reduction="mean")
文章浏览阅读1.7k次,点赞2次,收藏10次。CH3线性代数方法建模overview线性代数是以向量和矩阵为对象,以实向量空间为背景的一种抽象数学工具,它的应用遍及科学技术和国民经济各个领域。本篇通过基因遗传学、投入产出模型等几个例子阐述以线性代数为主要工具建立数学模型的一般方法和步骤。3.1常染色体基因遗传常染色体基因遗传中,后代是从每个亲本的基因对中各继承一个基因,形成自己的基因对。模型一 植物基因的分布植物基因对为AA、Aa..._线性代数建模
文章浏览阅读382次,点赞7次,收藏9次。2023 全年都在降本增效,节能开猿的浪潮下度过。虽然本文是给大家讲防御性编程如何实践,但终究只是博君一笑,请勿当真。这里我还是希望每一个互联网打工人都能平稳度过这波寒冬。积蓄力量,多思考,多元发展。在来年,春暖花开,金三银四之月,都能找到自己满意的工作,得到属于自己的果实。_防御编程
文章浏览阅读4.7k次,点赞8次,收藏13次。今天在学习Mybaits的时候,根据教程写出了一个第一个程序——从数据库读取一条数据并打印。当一切都就绪了:user.javaUserMapper.xmlmybatis-config.xml测试类依葫芦画瓢地写下来,以为没问题了,运行这个测试方法,竟然报错了:org.apache.ibatis.exceptions.PersistenceException: ### Err..._unknown initial character 255