java项⽬模式有哪些类型_Java中⼏种常见的设计模式--⼯⼚设
计模式
⼀、什么是⼯⼚设计模式
当需要获取对象时,并不是直接去实例化,⽽是通过⼀个⼯⼚类间接获取,以实现创建者和调⽤者的分离,实现更好的解耦。直⽩⼀点说,就是调⽤者不⽤也根本不会知道对象时如何创建的,它只需要⼯⼚提出条件即可,由⼯⼚来根据提交创建具体的实例。
⼆、使⽤场景
当框架需要深度解耦,⾼度可扩展时就需要⽤到⼯⼚设计模式,这种设计模式在SpringBoot、Mybatis框架中很常见。
三、⼏种类型
如果详细划分,⼯⼚设计模式可细分为:
简单⼯⼚模式(静态⼯⼚模式)
⼯⼚⽅法模式
抽象⼯⼚模式
接下来,我们将⼀个⼀个详细讲解。再此之前,有⼏个⾯向对象设计的基本原则,理解这些原则可以帮助我们更好地理解⼯⼚设计模式。
OCP(开闭原则,Open-Close-Principle):⼀个软件实体应当对扩展开放,对修改关闭。
DIP(依赖倒置原则,Dependence Invision Principle):要针对接⼝编程,不要针对实现编程。
LoD(迪⽶特法则,Law of Demeter):只与你的朋友通信,⽽避免与陌⽣⼈通信。
四、简单⼯⼚模式
举个例⼦,假如我们在做⼀个⽤户注册功能,再Dao中提供注册服务,⽤户信息的实体类如下:
public classUser {publicString name;publicString password;publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicString getPassword() {returnpassword;
}public voidsetPassword(String password) {this.password =password;
}
}
我们打算把新注册的⽤户信息插⼊到数据库,假设我们⽬前使⽤的数据库是Mysql,我们的Dao接⼝和实现类分别如下:
public interfaceDaoRegisterService {voidinsert(User user);
}
public class DaoMysqlRegisterServiceImpl implementsDaoRegisterService {
@Overridepublic voidinsert(User user) {
System.out.print("注册⽤户:"+user.name+"到Mysql数据库成功");
}
}
在客户端调⽤结果如下:
public classClient {public static voidmain(String[] args){
User user=newUser();
user.name="张三";
user.password="123456";
DaoRegisterService registerService=newDaoMysqlRegisterServiceImpl();
registerService.insert(user);
}
}
结果:
注册⽤户:张三到Mysql数据库成功
现在这种做法完全可以满⾜我们的使⽤要求,但随着业务量的增加,Mysql数据库越发不能满⾜我们的业务需要,我们需要使⽤性能更好的Oracle数据库,于是我们需要再写⼀个Oracle的Dao服务实现类。
public class DaoOracleRegisterServiceImpl implementsDaoRegisterService {
@Overridepublic voidinsert(User user) {oracle ocp培训
System.out.print("注册⽤户:"+user.name+"到Oracle数据库成功");
}
}
我们的客户端也需要进⾏对应的更改。
public classClient {public static voidmain(String[] args){
User user=newUser();
user.name="张三";
user.password="123456";
DaoRegisterService registerService=newDaoOracleRegisterServiceImpl();
registerService.insert(user);
}
}
结果:
注册⽤户:张三到Oracle数据库成功
项⽬⾥如果只有⼀处需要将DaoMysqlRegisterServiceImpl类改为DaoOracleRegisterServiceImpl的地⽅还好,如果有⼗⼏处、⼏⼗处,那么这个修改⼯作显然出⼒不讨好。
那如何解决这个问题呢,让程序框架更容易实现扩展功能,这个时候我们就需要⽤到⼯⼚设计模式。⾸先我们创建⼀个⼯⼚类,⾥⾯有个静态⽅法,通过数据名称可为我们提供DaoRegisterService实例。
public classDaoFactory {public staticDaoRegisterService createDaoRegisterService(String databaseName)
{switch(databaseName){case "mysql":return newDaoMysqlRegisterServicelImpl();case "oracle":return newDaoOracleRegisterServiceImpl();default:return null;
}
}
}
在客户端,我们只需要向⼯⼚输⼊条件,就可以得到我们想要的对象实例,⽽不需要⾃⼰去创建。
public classClient {public static voidmain(String[] args){
User user=newUser();
user.name="张三";
user.password="123456";//项⽬初期//DaoService Service=
DaoService Service= ateDaoRegisterService("oracle");
Service.insert(user);
}
}
现在我们来看看这种简单⼯⼚模式的优缺点,优点是它很简单,也确实能实现⼯⼚模式的功能,即调⽤者和创建者实现解耦。当同时这种简单⼯⼚模式也存在却缺点,现在我们只有两个⽬标(DaoMysqlRegisterServiceImpl和DaoOracleRegisterServiceImpl服务),当我们⽬标增多时(⽐如增加⼀个DaoDB2RegisterServiceImpl),我们就需要更改⼯⼚类的内部代码,使其兼容新的内容,这明显违背了我们上⾯讲的开闭原则,即宁愿增加新的类来扩展,也不要对原来的类做修改,所以出现了⼯⼚⽅法模式。
五、⼯⼚⽅法模式
⼯⼚⽅法模式是对简单⼯⼚模式的抽象升级,将⼯⼚这个概念抽象出来成为接⼝,然后针对每种⽬标实现类创建⼀个⼯⼚实现,⼀对⼀来实现,当新增了⽬标实现,只要同时新增⼀个⼯⼚实现即可。
同样还是上⾯数据库的例⼦,我们对⼯⼚类升级未接⼝,然后对每⼀个⽬标创建⼀个⼯⼚接⼝的实现,当有新的⽬标出现时,只需要再增加对应的⼯⼚接⼝实现,⽽不需要对原来的代码做任何的修改。
⼯⼚接⼝:
public interfaceDaoFactory {
DaoRegisterService createDaoRegisterService();
}
mysql的⼯⼚实现类:
public class DaoMysqlFactory implementsDaoFactory {
@OverridepublicDaoRegisterService createDaoRegisterService() {return newDaoMysqlRegisterServiceImpl();
}
}
oracle的⼯⼚实现类:
public class DaoOracleFactory implementsDaoFactory {
@OverridepublicDaoRegisterService createDaoRegisterService() {return newDaoOracleRegisterServiceImpl();
}
}
客户端:
public classClient {public static voidmain(String[] args){
User user=newUser();
user.name="张三";
user.password="123456";//项⽬初期//DaoFactory daoFactory=new DaoMysqlFactory();//DaoRegisterService registerService= ateDaoRegisterService();//registerService.insert(user);
DaoFactory daoFactory=newDaoOracleFactory();
DaoRegisterService ateDaoRegisterService();
registerService.insert(user);
}
}
当项⽬需要再拓展⼀个DB2的服务时,只需要再增加⼀个DB2的Dao实现类和⼀个⼯⼚实现类即可。
再说说⼯⼚⽅法模式的优缺点以及使⽤场景
优点:
⽤户只需关⼼所需产品对应的⼯⼚,⽆须关⼼创建细节(屏蔽产品类),甚⾄不需要知道具体产品的类名;
典型的解耦框架,⾼层模块需要知道产品的抽象类,其他的实现类都不⽤关⼼;
良好的封装性,代码结构清晰,优秀的扩展性,同时符合开闭原则。
缺点:
在添加新产品时成对增加了类的个数,增加了系统的复杂度,编译和运⾏更多的类也会增加系统的开销;
考虑到可扩展性引⼊抽象层,在客户端代码中均使⽤抽象层进⾏定义,增加了系统的抽象性和理解难度。
使⽤场景:
需要灵活、可扩展的框架时;
当⼀个类(⽐如客户端类)不知道所需要的对象的类时(需要知道其对应的⼯⼚);
个类通过其⼦类来确定创建那个对象。
六、抽象⼯⼚模式
抽象⼯⼚模式的定义是:为创建⼀组相关或相互依赖的对象提供⼀个接⼝,⽽且⽆需指定他们的具体类。
抽象⼯⼚模式是⼯⼚⽅法模式的泛化版,即⼯⼚⽅法模式只是抽象⼯⼚模式的⼀种特殊情况。
我们还是以Dao提供的数据库服务为例,上⾯我们提供了⼀个⽤户注册的服务,下⾯我们再提供⼀个⽤户登录的服务。
接⼝:
public interfaceDaoLoginService {voidcheckValid(User user);
}
Mysql实现类:
public class DaoMysqLoginServicelImpl implementsDaoLoginService {
@Overridepublic voidcheckValid(User user){if (user.name=="张三"&&user.password=="123456"){
System.out.println("使⽤Mysql验证⽤户:"+user.name+"通过");
}else{
System.out.println("使⽤Mysql验证⽤户:"+user.name+"失败");
}
}
}
Oracle实现类
public class DaoOracleLoginServiceImpl implementsDaoLoginService {
@Overridepublic voidcheckValid(User user){if (user.name=="张三"&&user.password=="123456"){
System.out.println("使⽤Oracle验证⽤户:"+user.name+"通过");
}else{
System.out.println("使⽤Oracle验证⽤户:"+user.name+"失败");
}
}
}
我们让⼯⼚接⼝可以提供所有的服务
public interfaceDaoFactory {
DaoRegisterService createDaoRegisterService();
DaoLoginService createDaoLoginService();
}
public class DaoMysqlFactory implementsDaoFactory {
@OverridepublicDaoRegisterService createDaoRegisterService() {return newDaoMysqlRegisterServiceImpl(); }
@OverridepublicDaoLoginService createDaoLoginService() {return newDaoMysqLoginServicelImpl();
}
}
public class DaoOracleFactory implementsDaoFactory {
@OverridepublicDaoRegisterService createDaoRegisterService() {return newDaoOracleRegisterServiceImpl(); }
@OverridepublicDaoLoginService createDaoLoginService(){return newDaoOracleLoginServiceImpl();
}
}
使⽤客户端验证如下:
public classClient {public static voidmain(String[] args){
User user=newUser();
user.name="张三";
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论