目录
-
- 一、工厂模式
- 二、工厂方法模式的优缺点
-
- 1、优点
- 2、缺点
- 三、模拟场景
- 四、违背原则方案
-
- 1、思路清晰,简单明了
- 2、但是,似乎违反了一些设计原则:
- 五、通过工厂方法模式重构代码
-
- 1、定义购买接口
- 2、普通用户实现类
- 3、京东plus实现类
- 4、企业采购实现类
- 5、创建用户工厂
- 6、测试类
- 六、关于《Java核心技术》第十二版
-
- 1、适用人群
- 2、精彩书摘
一、工厂模式
工厂模式也称简单工厂模式,是创建型设计模式的一种,这种设计模式提供了按需创建对象的最佳方式。同时**,这种创建方式不会对外暴露创建细节,通常会通过一个统一的接口创建所需对象。**
定义一个创建对象的接口,让其子类自己决定将哪一个工厂类实例化,工厂模式使创建过程延迟到子类中进行。
简单地说,就是为了给代码结构提供扩展性,屏蔽每一个功能类中的具体实现逻辑。这种方式便于外部更加简单地调用,同时也是去掉众多ifelse的最佳手段。当然,这种设计模式也有一些缺点,例如需要实现的类比较多、难以维护。开发成本高等,但这些问题都可以通过结合不同的设计模式逐步优化。
二、工厂方法模式的优缺点
1、优点
(1)良好的封装性、代码结构清晰。
如一个调用者想创建一个对象,只需要知道其名称即可,降低了模板间的耦合。
(2)扩展性好。
如果想增加一个产品,只需扩展一个工厂类即可。
(3)屏蔽产品类
调用者只关心产品的接口。
(4)典型的解耦框架
2、缺点
每增加一个产品,就需要增加一个产品工厂的类,增加了系统的复杂度。
三、模拟场景
通过普通用户、京东plus、企业采购购买《Java核心技术》书籍为例,不同的购买人,优惠和流程都是不一样的。
三种用户的购买接口:
序号 | 类型 | 接口 |
---|---|---|
1 | 1 | void buySaviourByGeneralUser(int productId) |
2 | 2 | double buySaviourByJDPlus(int productId, int vipLevel, boolean promotions) |
3 | 3 | Sring buySaviourByEnterprise(int productId, String company, String name) |
普通用户、京东plus、企业采购三个接口的接口参数不同,返回值也不同。
四、违背原则方案
1、思路清晰,简单明了
如果增加其它类型,继续增加ifelse即可。
2、但是,似乎违反了一些设计原则:
- 单一职责原则:指一个类或者模块应该有且只有一个改变的原因。
- 开闭原则:软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的。
- 接口隔离原则:尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。
package com.guor.beanutil.factory;
public class Shopping {
public static void main(String[] args) {
// 普通用户1
buyBook(1, 1, 1);
// 京东plus2
buyBook(1, 1, 2);
// 企业采购3
buyBook(1, 1, 3);
}
/**
* 购买Java核心技术
*
* 一顿操作猛如虎,实际购买流程比这个复杂的多,只是简单模拟
*/
public static void buyBook(int productId, int userId, int userType) {
// 按照不同的用户类型(普通用户1、京东plus2、企业采购3)
if (userType == 1) {// 普通用户1
// 购买Java核心技术
buyBookByGeneralUser(productId);
} else if (userType == 2) {// 京东plus2
// 通过userId到数据库查询会员等级,优惠力度不一样
int vipLevel = 1;
// 通过产品id查询商品是否参加活动
boolean promotions = true;
// 购买Java核心技术
buyBookByJDPlus(productId, vipLevel, promotions);
} else if (userType == 3) {// 企业采购3
// 根据userId到company表中查询
String company = "哪吒技术有限公司";
// 根据userId到用户表查询
String name = "哪吒";
// 购买Java核心技术
buyBookByEnterprise(productId, company, name);
}
}
/**
* 普通用户1
*
* @param productId 商品id
*/
public static void buyBookByGeneralUser(int productId){
// 一些不为人知的业务处理
System.out.println("普通用户购买了Java核心技术");
}
/**
* 京东plus2
*
* @param productId 商品id
* @param vipLevel 会员等级
* @param promotions 是否有活动
* @return 京东plus为您节省了多少钱
*/
public static double buyBookByJDPlus(int productId, int vipLevel, boolean promotions){
// 一些不为人知的业务处理
System.out.println("京东plus购买了Java核心技术");
return 99;
}
/**
* 企业采购3
*
* @param productId 商品id
* @param company 公司名称
* @param name 采办人姓名
* @return 具体采购详情
*/
public static String buyBookByEnterprise(int productId, String company, String name){
// 一些不为人知的业务处理
System.out.println("企业采购了Java核心技术");
return "哪吒为粉丝采购了Java核心技术";
}
}
五、通过工厂方法模式重构代码
现将代码通过工厂方法模式进行重构,重构之后,代码会更加的清晰明了,再拓展的时候,,再也不用写那么多的ifelse了,添加接口实现类,并通过工厂类构建实例即可。代码结构清晰明了,可复用性强、拓展性更好,符合何单一职责原则、开闭原则、接口隔离原则。
1、定义购买接口
package com.guor.beanutil.factory;
import java.util.Map;
/**
* 购买《Java核心技术》
*/
public interface IBuyBook {
void buyBook(Integer productId, Integer userId, Map<String, Object> otherMsg);
}
2、普通用户实现类
package com.guor.beanutil.factory;
import java.util.Map;
/**
* 普通用户1
*/
public class BuyBookByGeneralUser implements IBuyBook {
@Override
public void buyBook(Integer productId, Integer userId, Map<String, Object> otherMsg) {
// 一些不为人知的业务处理
System.out.println("普通用户购买了Java核心技术");
}
}
3、京东plus实现类
package com.guor.beanutil.factory;
import java.util.Map;
/**
* 京东plus2
*/
public class BuyBookByJDPlus implements IBuyBook {
@Override
public void buyBook(Integer productId, Integer userId, Map<String, Object> otherMsg) {
// 一些不为人知的业务处理
System.out.println("京东plus购买了Java核心技术");
}
}
4、企业采购实现类
package com.guor.beanutil.factory;
import java.util.Map;
/**
* 企业采购3
*/
public class BuyBookByEnterprise implements IBuyBook {
@Override
public void buyBook(Integer productId, Integer userId, Map<String, Object> otherMsg) {
// 一些不为人知的业务处理
System.out.println("哪吒为粉丝采购了Java核心技术");
}
}
5、创建用户工厂
这里定义了一个用户的工厂类,在里面按照类型实现不同的用户实例,代码清晰明了,后续新增新用户,在工厂类新增即可。
package com.guor.beanutil.factory;
import java.util.HashMap;
import java.util.Map;
public class BuyBookFactory {
public IBuyBook getBuyBook(int userType){
if (userType == 1) {// 普通用户1
return new BuyBookByGeneralUser();
} else if (userType == 2) {// 京东plus2
return new BuyBookByJDPlus();
} else if (userType == 3) {// 企业采购3
return new BuyBookByEnterprise();
}else{
System.out.println("不存在此用户类型...");
return null;
}
}
6、测试类
public static void main(String[] args) {
BuyBookFactory buyBookFactory = new BuyBookFactory();
// 普通用户1
IBuyBook buyBook1 = buyBookFactory.getBuyBook(1);
buyBook1.buyBook(1, 1, null);
// 京东plus2
Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("vipLevel", 1);// 会员等级
map2.put("promotions", true);// 是否参加活动
IBuyBook buyBook2 = buyBookFactory.getBuyBook(2);
buyBook1.buyBook(1, 1, map2);
// 企业采购3
Map<String, Object> map3 = new HashMap<String, Object>();
map3.put("company", "哪吒技术有限公司");// 公司名称
map3.put("name", "哪吒");// 采办人姓名
IBuyBook buyBook3 = buyBookFactory.getBuyBook(3);
buyBook3.buyBook(1,1,map3);
}
}
六、关于《Java核心技术》第十二版
1、适用人群
本书适合想正式、系统地学习Java,并打算将Java应用到实际工程项目中的初中级开发者阅读。
2、精彩书摘
- 除JDK和Java IDE外,详细介绍如何使用JShell工具快速、方便地尝试Java代码。
- 利用丰富示例全面介绍Java的基本语法。
- 详细解释Java语言封装机制,并提供面向对象程序设计(OOP)建议。
- 利用示例讲解Java继承的设计技巧。
- 通过清晰明了的介绍,帮助读者充分理解并有效使用相对复杂的反射。
- 利用接口和lambda表达式,帮助读者提升Java面向对象编程能力。
- 全面介绍Java异常处理,并提供实用的调试技巧。
- 重点强调泛型程序设计和强类型机制,避免不安全的强制类型转换。
- 帮助读者有效使用Java平台的集合框架和预建标准集合。
- 提供GUI程序设计和Swing
- GUI工具包使用指南,指导读者创建跨平台的图形用户界面。
- 全面介绍Java并发和多线程编程所需的工具。
本书经全面修订,以涵盖Java 17的新特性。新版延续之前版本的优良传统,利用清晰明了的示例加以解释,着力让读者在充分理解Java语言和Java类库的基础上,灵活应用Java提供的高级特性,具体包括面向对象程序设计、反射与代理、接口与内部类、异常处理、泛型程序设计、集合框架、事件监听器模型、图形用户界面设计和并发。整本书不仅可以让读者深入了解设计和实现Java应用程序涉及的所有基础知识和Java特性,还会帮助读者掌握开发Java程序所需的全部基本技能。
要想了解有关Java 17的高级特性,包括企业特性、模块系统、网络、安全和高级UI编程,请期待《Java核心技术 卷Ⅱ高级特性(原书第12版)》。