你还在处处 new 对象吗?java
单身狗:我没对象,new 怎么了?git
new 对象自己是没问题的,但也不能所有 new 关键字走天下,其实有更好的方式,合适的时候能够试试工厂模式,代码会更优雅。程序员
顾名思义,工厂模式中的 "工厂" 指的是建立对象的工厂,它提供了一种建立对象的最佳方式,也就是工厂模式。github
工厂模式的好处是这些对象不须要暴露自身的建立过程,统一由工厂模式进行建立和提供,隐藏了建立细节,避免了错误的建立对象的形式,也减小了重复建立冗余代码。面试
通常状况下,工厂模式能够细分为三类:spring
不过在设计模式权威书籍《设计模式:可复用面向对象软件的基础》一书中,简单工厂模式只是工厂方法模式的一个特例而已。设计模式
因此,从权威的角度说,工厂模式只分为: 工厂模式 和 抽象工厂模式 两大类。intellij-idea
但无论白猫黑猫,能抓老鼠的就是好猫,设计模式亦是如此,无论怎么分类,这些模式都是程序员们历年过往经验的浓缩,都是值得学习和借鉴的。ide
因此,本文栈长从细分的角度带你们来实战下这三个工厂设计模式。工具
好比 XX 公司是作支付的,公司有几大类的客户:电商商户、银行客户、代理商……
建立这些客户的时候咱们能够用简单工厂模式来实现看看。
新建客户基类:
能够把全部客户公共的信息放到一个客户基类中,好比:客户名、客户类型等,全部的客户继承这个抽象基类。
/** * 客户 * @author: 栈长 * @from: 公众号Java技术栈 */ @Data @NoArgsConstructor @AllArgsConstructor public abstract class Customer { /** * 客户名称 */ private String name; /** * 客户类型 */ private String type; }
新建电商商户类:
/** * 商户 * @author: 栈长 * @from: 公众号Java技术栈 */ @Data @ToString(callSuper = true) public class Merchant extends Customer { /** * 合同类型 */ private int contractType; /** * 结算周期(天) */ private int settmentDays; public Merchant(String name, String type) { super(name, type); } }
新建银行客户类:
/** * 银行客户 * @author: 栈长 * @from: 公众号Java技术栈 */ @Data @ToString(callSuper = true) public class BankPartner extends Customer { /** * 银行编码 */ private String code; /** * 银行地址 */ private String address; public BankPartner(String name, String type) { super(name, type); } }
新建代理商类:
/** * 代理商 * @author: 栈长 * @from: 公众号Java技术栈 */ @Data @ToString(callSuper = true) public class Agent extends Customer { /** * 代理周期 */ private int period; /** * 代理产品 */ private int[] products; public Agent(String name, String type) { super(name, type); } }
新增简单工厂类:
新建一个简单工厂,提供一个公共静态方法,根据不一样的客户类型建立不一样的客户。
/** * 客户简单工厂 * @author: 栈长 * @from: 公众号Java技术栈 */ public class CustomerFactory { private static Merchant createMerchant(String type, String name) { return new Merchant(type, name); } private static BankPartner createBankPartner(String type, String name) { return new BankPartner(type, name); } private static Agent createAgent(String type, String name) { return new Agent(type, name); } public static Customer create(String type, String name) { if ("M".equals(type)) { return createMerchant(type, name); } else if ("B".equals(type)) { return createBankPartner(type, name); } else if ("A".equals(type)) { return createAgent(type, name); } return null; } }
新建测试类:
/** * @author: 栈长 * @from: 公众号Java技术栈 */ public class Test { public static void main(String[] args) { Customer merchant = CustomerFactory.create("M", "Java技术栈商户"); System.out.println(merchant); Customer bankPartner = CustomerFactory.create("B", "Java技术栈银行客户"); System.out.println(bankPartner); Customer agent = CustomerFactory.create("A", "Java技术栈代理商"); System.out.println(agent); } }
输出结果:
本节教程全部实战源码已上传到这个仓库:
能够看出简单工厂的使用很简单,就是耦合性过高了。
第一,对象和基类之间是基于继承的。
第二,工厂类耦合了不一样对象的建立,若是对象类型不是固定或者常常变更的,就要频繁修改工厂类,好比我如今要再加一种客户,就必需要改动工厂类,不符开闭原则。
因此,简单工厂只适用于固定类型对象的建立。
工厂方法就是为某类产品提供一个工厂接口,而后为每一个产品提供一个工厂实现类。
废话少说,咱们将简单工厂的示例用工厂方法再改造一下。
新建工厂方法接口:
/** * 工厂方法客户接口 * @author: 栈长 * @from: 公众号Java技术栈 */ public interface CustomerFactory { Customer create(String type, String name); }
新建商户工厂实现类:
/** * 商户工厂 * @author: 栈长 * @from: 公众号Java技术栈 */ public class MerchantFactory implements CustomerFactory { @Override public Customer create(String type, String name) { return new Merchant(type, name); } }
新建银行客户工厂实现类:
/** * 银行客户工厂 * @author: 栈长 * @from: 公众号Java技术栈 */ public class BankPartnerFactory implements CustomerFactory { @Override public Customer create(String type, String name) { return new BankPartner(type, name); } }
新建代理商工厂实现类:
/** * 代理商工厂 * @author: 栈长 * @from: 公众号Java技术栈 */ public class AgentFactory implements CustomerFactory { @Override public Customer create(String type, String name) { return new Agent(type, name); } }
新建测试类:
/** * @author: 栈长 * @from: 公众号Java技术栈 */ public class Test { public static void main(String[] args) { System.out.println("------工厂模式-工厂方法------"); CustomerFactory merchantFactory = new MerchantFactory(); Customer merchant = merchantFactory.create("M", "Java技术栈商户"); System.out.println(merchant); CustomerFactory bankPartnerFactory = new BankPartnerFactory(); Customer bankPartner = bankPartnerFactory.create("B", "Java技术栈银行客户"); System.out.println(bankPartner); CustomerFactory agentFactory = new AgentFactory(); Customer agent = agentFactory.create("A", "Java技术栈代理商"); System.out.println(agent); } }
输出结果:
本节教程全部实战源码已上传到这个仓库:
能够看出,工厂方法也是挺简单易用的,耦合性问题也解决了,每增长一个产品就新增一个产品工厂实现类就好了,扩展性很是好。
但也有一个问题,若是产品很是多,那势必会形成工厂实现类泛滥,另一种可怕的场景就是,若是涉及到工厂接口变动,工厂实现类的维护简直就是一种恶梦。
工厂方法中一个工厂只能建立一个对象,若是如今每次建立客户的时候都须要同时建立一份客户扩展资料,那就能够考虑使用抽象工厂。
新建客户扩展基类:
能够把全部客户公共的扩展信息放到一个客户扩展基类中,好比:客户曾用名、客户扩展说明等,全部的客户继承这个扩展抽象基类。
/** * 客户扩展 * @author: 栈长 * @from: 公众号Java技术栈 */ @Data @NoArgsConstructor public abstract class CustomerExt { /** * 客户曾用名 */ private String formerName; /** * 客户扩展说明 */ private String note; }
新建商户扩展类:
/** * 商户 * @author: 栈长 * @from: 公众号Java技术栈 */ @Data @ToString(callSuper = true) public class MerchantExt extends CustomerExt { /** * 介绍人 */ private int introduceName; /** * 介绍人电话 */ private String introduceTel; }
新建银行客户扩展类:
/** * 银行客户扩展 * @author: 栈长 * @from: 公众号Java技术栈 */ @Data @ToString(callSuper = true) public class BankPartnerExt extends CustomerExt { /** * 分行个数 */ private int branchCount; /** * ATM个数 */ private int atmCount; }
新建代理商扩展类:
/** * 商户 * @author: 栈长 * @from: 公众号Java技术栈 */ @Data @ToString(callSuper = true) public class AgentExt extends CustomerExt { /** * 来源 */ private String source; /** * 资质 */ private String certification; }
新建抽象工厂接口:
/** * 抽象工厂客户接口 * @author: 栈长 * @from: 公众号Java技术栈 */ public interface CustomerFactory { Customer createCustomer(String type, String name); CustomerExt createCustomerExt(); }
新建商户工厂实现类:
/** * 商户工厂 * @author: 栈长 * @from: 公众号Java技术栈 */ public class MerchantFactory implements CustomerFactory { @Override public Customer createCustomer(String type, String name) { return new Merchant(type, name); } @Override public CustomerExt createCustomerExt() { return new MerchantExt(); } }
新建银行客户工厂实现类:
/** * 银行客户工厂 * @author: 栈长 * @from: 公众号Java技术栈 */ public class BankPartnerFactory implements CustomerFactory { @Override public Customer createCustomer(String type, String name) { return new BankPartner(type, name); } @Override public CustomerExt createCustomerExt() { return new BankPartnerExt(); } }
新建代理商工厂实现类:
/** * 代理商工厂 * @author: 栈长 * @from: 公众号Java技术栈 */ public class AgentFactory implements CustomerFactory { @Override public Customer createCustomer(String type, String name) { return new Agent(type, name); } @Override public CustomerExt createCustomerExt() { return new AgentExt(); } }
新建测试类:
/** * @author: 栈长 * @from: 公众号Java技术栈 */ public class Test { public static void main(String[] args) { System.out.println("------工厂模式-抽象工厂------"); CustomerFactory merchantFactory = new MerchantFactory(); Customer merchant = merchantFactory.createCustomer("M", "Java技术栈商户"); CustomerExt merchantExt = merchantFactory.createCustomerExt(); System.out.println(merchant); System.out.println(merchantExt); CustomerFactory bankPartnerFactory = new BankPartnerFactory(); Customer bankPartner = bankPartnerFactory.createCustomer("B", "Java技术栈银行客户"); CustomerExt bankPartnerExt = bankPartnerFactory.createCustomerExt(); System.out.println(bankPartner); System.out.println(bankPartnerExt); CustomerFactory agentFactory = new AgentFactory(); Customer agent = agentFactory.createCustomer("A", "Java技术栈代理商"); CustomerExt agentExt = agentFactory.createCustomerExt(); System.out.println(agent); System.out.println(agentExt); } }
输出结果:
能够看出,抽象工厂和工厂方法十分相似,只不过抽象工厂里面只生产一个对象,而抽象工厂能够生产多个对象。
抽象工厂缺点也很明显,第一就是和工厂方法同样工厂类很是多,第二就是扩展很是麻烦,好比我如今要为每一个客户类型再加一份客户特殊资料,那全部涉及到抽象工厂的工厂类都要改,是否是要疯了。。
若是有多个属于同一种类型的类,能够考虑使用工厂模式,统一提供生成入口,能从必定程度上解耦,扩展方便,也不用再处处 new 对象了。
但话又说回来,从示例能够看出,若是使用或者设计不当也会带来维护上的工做量。
本节教程全部实战源码已上传到这个仓库:
好了,今天的分享就到这里了,后面栈长我会更新其余设计模式的实战文章,公众号Java技术栈第一时间推送。Java技术栈《设计模式》系列文章陆续更新中,请你们持续关注哦!
最后,以为个人文章对你用收获的话,动动小手,给个在看、转发,原创不易,栈长须要你的鼓励。
版权申明:本文系公众号 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,禁止抄袭、洗稿,请自重,尊重你们的劳动成果和知识产权,抄袭必究。
近期热文推荐:
1.1,000+ 道 Java面试题及答案整理(2021最新版)
2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!
3.阿里 Mock 工具正式开源,干掉市面上全部 Mock 工具!
4.Spring Cloud 2020.0.0 正式发布,全新颠覆性版本!
以为不错,别忘了随手点赞+转发哦!