反射与工厂模式:早餐店的发展之路
实际开发中,接口的主要作用是为了不用层提供有一个操作的标准,如果直接实例化了类的操作【用new
关键字来实例化】,则一定存在耦合问题,可以用工厂模式解决此问题。
接下来用一个店主开早餐店的经历来阐述反射与工厂模式。
店主的经历如下:简单的早餐店 --> 增加西式早餐 --> 多种早餐需求 --> 拓展业务。
简单的早餐店
店主起初想开个简单的早餐店,就经营简单的早餐业务,所以创建了一个简单的工厂来生产对应的早餐服务。
BreakfastService
package javabase.service;
public interface BreakfastService {void cookIt();
}
Breakfast
package javabase.entity;
import javabase.service.BreakfastService;
public class Breakfast implements BreakfastService {@Overridepublic void cookIt() {System.out.println("====我正在做一份美味的早餐呢!====>");}
}
MyFactory
package javabase.factory;
import javabase.entity.Breakfast;
import javabase.service.BreakfastService;
public class Myfactory {private Myfactory(){}public static BreakfastService getBreakFast(String name){//判断传来的是否是美味的早餐的名字if("Breakfast".equals(name)){//如果是则返回对应的实例化对象return new Breakfast();}return null;}
}
Main
package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
public class Main {public static void main(String[] args) {//开始买早餐咯BreakfastService breakfastService = Myfactory.getBreakFast("Breakfast");breakfastService.cookIt();}
}
运行结果
====我正在做一份美味的早餐呢!====>
增加西式早餐
店主开店之后,生意火爆,有顾客跟店长反应,要不再开多一个西式的早餐业务?店主想了想,如果品种再多一点的话,说不定客户会更多呢!于是就创建了对应的西式早餐服务,然后再添加到对应的工厂里。
EastBreakfast
package javabase.entity;
import javabase.service.BreakfastService;
public class EastBreakfast implements BreakfastService {@Overridepublic void cookIt() {System.out.println("====我正在做一份美味的西式早餐呢!====>");}
}
那么店主的工厂得开始加工了,再来生产西式早餐。
MyFactory
package javabase.factory;
import javabase.entity.Breakfast;
import javabase.entity.EastBreakfast;
import javabase.service.BreakfastService;
public class Myfactory {private Myfactory(){}public static BreakfastService getBreakFast(String name){//根据客户端传入的名字来判断客户端需要什么早餐if("Breakfast".equals(name)){//返回普通早餐的实例化return new BreakFast();}else if("EastBreakfast".equals(name)){//返回西式早餐的实例化return new EastBreakfast();}return null;}
}
Main
package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
public class Main {public static void main(String[] args) {//生产美味的早餐BreakfastService breakfastService = Myfactory.getBreakFast("Breakfast");breakfastService.cookIt();//生产美味的西式早餐BreakfastService eastBreakfast = Myfactory.getBreakFast("EastBreakfast");eastBreakfast.cookIt();}
}
运行结果
====我正在做一份美味的早餐呢!====>
====我正在做一份美味的西式早餐呢!====>
多种早餐需求
要知道,顾客就是上帝,近期许多顾客都向店主提要求说要中式早餐,日式早餐等不同品种的早餐?要是像增加西式早餐那样直接添加对应的实例化西式早餐对象代码的话,日后代码就变得冗长且难读,而且会浪费大量的时间在阅读工厂代码以及修改工厂代码上。如果每天店主都这样工作的话,恐怕会英年早逝。
这次店长灵光一闪,想到用反射来进行获取对应的早餐,所以工厂的代码修改如下。
MyFactory
//少了两行import *^_^*
package javabase.factory;
import javabase.service.BreakfastService;
public class Myfactory {private Myfactory(){}public static BreakfastService getBreakFast(String breakfastName){BreakfastService breakfastService = null;try {/*** 使用反射的方式来获取对应的早餐实例化对象* 使用Class的static方法forName(name)获取Class的实例化对象* 再调用newInstance()方法来实例化BreakfastService* 最后再进行类型转化*/breakfastService = (BreakfastService)Class.forName(breakfastName).newInstance();} catch (Exception e) {//如果出现任何异常直接返回nullreturn null;}return breakfastService;}
}
Main
package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
public class Main {public static void main(String[] args) {//生产美味的早餐,这次需要传递的就是完整的类名了【包.类】,就不能简单地写类名了BreakfastService breakfastService = Myfactory.getBreakFast("javabase.entity.Breakfast");breakfastService.cookIt();//生产美味的西式早餐BreakfastService eastBreakfastService = Myfactory.getBreakFast("javabase.entity.EastBreakfast");eastBreakfastService.cookIt();}
}
运行结果
====我正在做一份美味的早餐呢!====>
====我正在做一份美味的西式早餐呢!====>
这时,店主再加入中式早餐服务,则不需要再修改对应的工厂类。
ChineseBreakfast
package javabase.entity;import javabase.service.BreakfastService;public class ChineseBreakfast implements BreakfastService {@Overridepublic void cookIt() {System.out.println("====我正在做一份美味的中式早餐呢!====>");}
}
Main
package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
public class Main {public static void main(String[] args) {//生产美味的早餐,这次需要传递的就是完整的类名了【包.类】,就不能简单地串类名了BreakfastService breakfastService = Myfactory.getBreakFast("javabase.entity.Breakfast");breakfastService.cookIt();//生产美味的西式早餐BreakfastService eastBreakfastService = Myfactory.getBreakFast("javabase.entity.EastBreakfast");eastBreakfastService.cookIt();//生产中式早餐BreakfastService chineseBreakfastService = Myfactory.getBreakFast("javabase.entity.ChineseBreakfast");chineseBreakfastService.cookIt();}
}
运行结果
====我正在做一份美味的早餐呢!====>
====我正在做一份美味的西式早餐呢!====>
====我正在做一份美味的中式早餐呢!====>
拓展业务
通过反射的机制,店长有了更多的时间来进行思考其他的事,时间也更加充裕了。店长又突发奇想,如果我们的店再兼做午餐和晚餐会怎样呢?加多几个工厂如何?可是如果未来要发展更多的餐饮业务,就要加更多个工厂,那每个工厂维护起来,岂不是要麻烦死,店长可不想因为此事而秃顶。店长经过上次经历后,决定,用泛型加反射来搞事情。
所以店长又再次决定修改工厂代码,加入泛型。
MyFactory
package javabase.factory;
import javabase.service.BreakfastService;
public class Myfactory {private Myfactory(){}public static <T> T getService(String serviceName){T service = null;try {/*** 使用反射的方式来获取对应的早餐实例化对象* 使用Class的static方法forName(name)获取Class的实例化对象* 再调用newInstance()方法来实例化BreakfastService* 最后再进行类型转化,这里用泛型的转化*/service = (T) Class.forName(serviceName).newInstance();} catch (Exception e) {//如果出现任何异常直接返回nullreturn null;}return service;}
}
此时,店长再加入午餐业务
LunchService
package javabase.service;
public interface LunchService {void cookLunch();
}
加入中式午餐服务
package javabase.entity;
import javabase.service.LunchService;
public class ChineseLunch implements LunchService {@Overridepublic void cookLunch() {System.out.println("====我正在做一份不一样的中式午餐呢!====>");}
}
两种业务进行,同个工厂进行生产两种不同的业务
Main
package javabase;
import javabase.factory.Myfactory;
import javabase.service.BreakfastService;
import javabase.service.LunchService;
import java.util.List;public class Main {public static void main(String[] args) {//生产中式早餐 --->早餐业务BreakfastService breakfastService = Myfactory.getService("javabase.entity.ChineseBreakfast");breakfastService.cookIt();//生产中式午餐 --->午餐业务LunchService lunchService = Myfactory.getService("javabase.entity.ChineseLunch");lunchService.cookLunch();}
}
运行结果
====我正在做一份美味的中式早餐呢!====>
====我正在做一份不一样的中式午餐呢!====>
最后,店主总算是可以拓展不同的餐饮领域了,不用再操心工厂生产的事咯!
总结
1.使用反射可以获取实例化对象的内容,与工厂模式结合能大大的减少代码中实例化对象的耦合。
2.最后使用泛型,而不直接使用Object呢?实际上最后的代码用Object也是可行的,但是在使用的时候要强制转化类型,而泛型则不用,相对来说,编译也会相对于Object安全。讲得通俗点就是,人家java底层开发人员开发出来个比原来还差的东西岂不是要被喷死。
3.代码的实用性以及扩展性,实用反射和泛型之后,能够很好的遵守开闭原则,就尽量减少对原来代码的修改。
4.减少代码的冗余,是检验代码质量的最基本要求,最好就做到高复用,低耦合啦。
5.代码的复制粘贴可能会有错误,参考的游客可以自行尝试敲下代码增加下印象,如果这篇博客能帮助你理解反射与工厂模式之间的关系就更好了。
反射与工厂模式:早餐店的发展之路相关推荐
- 设计模式之工厂类模式总结对比、简单工厂模式、工厂方法模式、抽象工厂模式、带反射的工厂模式、例子代码分析、最详细
1. 题目 假设某公司同时用SqlServer.MySql数据库,即会切换两数据库(不同数据库的sql语句有些许差异),同时,两数据库里均有对Users.Departments表的操作(sql代码不一 ...
- Java的反射机制 工厂模式综合讲解【转载自51CTO】
2019独角兽企业重金招聘Python工程师标准>>> Java的反射机制 工厂模式综合讲解 1.什么叫反射 Java.lang.reflect包下 正常情况下我们可以通过类实例化一 ...
- C#三层架构第九课之反射和工厂模式实现多数据库访问
反射和工厂模式实现不同数据库访问 在之前上课的基础上,使用反射和模唱模式,实现针对不同数据库的动态访问. 在之前的三层架构代码基础上进行修改. 使用三层架构+工厂模式,来实现一个程序访问多个数据库. ...
- java 反射实现 工厂模式_java – 用反射实现工厂模式
我正在实施工厂模式这是我的工厂类: class ProductFactory { private HashMap m_RegisteredProducts = new HashMap(); publi ...
- 设计模式(5)--三种工厂模式(披萨店)
工厂方法 工厂方法 Intent 定义了一个创建对象的接口,但是由子类决定要实例化的类是哪一个.工厂方法让类把是实例化推迟到子类. 抽象工厂 Intent 提供一个接口,用于创建相关或依赖对象的家族, ...
- 设计模式-创建型模式-工厂模式(工厂三兄弟)
设计模式-创建型模式-工厂模式(工厂三兄弟) 工厂模式分为简单工厂,工厂方法,抽象工厂. 简单工厂模式 一个接口,三个具体类,一个工厂,通过选择,生产出对应的对象. package demo2;pub ...
- C#之三十九 抽象工厂模式
在软件系统中,经常面临着"一系列相互依赖的对象"的创建工作:同时由于需求的变化,往往存在着更多系列对象的创建工作.如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种 ...
- 设计模式之工厂方法模式、抽象工厂模式的概念和实现及使用“反射技术+读取配置文件”的方法对工厂模式进行改进(软件工程综合实践课程第三周个人作业)
文章目录 一.实验目的 二.知识总结 1.工厂方法模式简介 2.抽象工厂模式简介 3.工厂模式小结 4.利用"反射技术+读取配置文件"的方法改进程序 三.实验内容 1. 工厂模式实 ...
- 三十八,反射的应用:工厂模式
2019独角兽企业重金招聘Python工程师标准>>> 1.通过反射调用类中的方法 示例: Person类: package com.ares.demo;interface Info ...
最新文章
- android 6.0动态权限的申请
- Oracle Golden Gate 系列十一 -- 配置 GG DDL 同步 说明 与 示例
- Javascript隐式转换
- Java StringBuilder getChars()方法与示例
- zabbix监控redis
- 计算机组成与系统结构概述
- 抽头延时信道模型matlab,频率选择性衰落信道模型研究与仿真.docx
- 华三ap设置无线服务器,H3C无线控制器V5版本配置AP上线的方法
- 光电耦合器简介以及作用
- 原生js页面滚动顶部显示滚动总进度条效果
- 两轮车ECU的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- 如何在Windows 10上控制多个显示器的功能
- 【转】qlv文件如何转换成mp4 怎样把下载好的qlv格式视频转换成MP4格式
- 看完你就知道原因了,这3类人不适合做自媒体,看看是不是你自己
- DSF data model
- Timer定时器详解
- 美女手机壁纸采集源码
- 大数据开发——Hive实战案例
- 数学建模美赛O奖论文研读启示录——从模仿开始
- [RK3288][Android6.0] Mali GPU基本知识
热门文章
- 算法-空瓶换啤酒问题
- new thread java_谈谈new Thread的弊端及Java四种线程池的使用
- soc低功耗电路设计应用-Zynq MPSoC
- 机器学习与Tensorflow(6)——LSTM的Tensorflow实现、Tensorboard简单实现、CNN应用
- python PyPDF2 添加水印
- 武装突袭3fps服务器不稳定,《武装突袭3》:不像FPS游戏,更像战争
- 关于安卓模拟器兼容的问题原因及解决方案
- oracle可以创建多个数据库实例吗_oracle 一个实例下可以建多个数据库么?
- 请教,关于monkey测试的时间间隔、执行次数、log中的动作次数
- Window bat rar压缩脚本