你还在到处 new 对象吗?
单身狗:我没对象,new 怎么了?
new 对象本身是没问题的,但也不能全部 new 关键字走天下,其实有更好的方式,合适的时候可以试试工厂模式,代码会更优雅。
顾名思义,工厂模式中的 "工厂" 指的是创建对象的工厂,它提供了一种创建对象的最佳方式,也就是工厂模式。
工厂模式的好处是这些对象不需要暴露自身的创建过程,统一由工厂模式进行创建和提供,隐藏了创建细节,避免了错误的创建对象的形式,也减少了重复创建冗余代码。
一般情况下,工厂模式可以细分为三类:
简单工厂模式
工厂方法模式
抽象工厂模式
不过在设计模式权威书籍《
设计模式:可复用面向对象软件的基础》一书中,简单工厂模式只是工厂方法模式的一个特例而已。
所以,从权威的角度说,工厂模式只分为: 工厂模式 和 抽象工厂模式 两大类。
但不管白猫黑猫,能抓老鼠的就是好猫,设计模式亦是如此,不管怎么分类,这些模式都是程序员们历年过往经验的浓缩,都是值得学习和借鉴的。
所以,本文栈长从细分的角度带大家来实战下这三个工厂设计模式。
比如 XX 公司是做支付的,公司有几大类的客户:电商商户、银行客户、代理商……
创建这些客户的时候我们可以用简单工厂模式来实现看看。
新建客户基类:
可以把所有客户公共的信息放到一个客户基类中,比如:客户名、客户类型等,所有的客户继承这个抽象基类。
/**
* 客户
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public abstract
class
Customer
{
/**
* 客户名称
*/
private String name
;
/**
* 客户类型
*/
private String type
;
}
新建电商商户类:
/**
* 商户
*/
@Data
@
ToString
(callSuper
=
true
)
public
class
Merchant
extends
Customer
{
/**
* 合同类型
*/
private int contractType
;
/**
* 结算周期(天)
*/
private int settmentDays
;
public
Merchant
(
String name
, String type
)
{
super
(name
, type
)
;
}
}
新建银行客户类:
/**
* 银行客户
*/
@Data
@
ToString
(callSuper
=
true
)
public
class
BankPartner
extends
Customer
{
/**
* 银行编码
*/
private String code
;
/**
* 银行地址
*/
private String address
;
public
BankPartner
(
String name
, String type
)
{
super
(name
, type
)
;
}
}
新建代理商类:
/**
* 代理商
*java学习交流:737251827 进入可领取学习资源及对十年开发经验大佬提问,免费解答!
*/
@Data
@
ToString
(callSuper
=
true
)
public
class
Agent
extends
Customer
{
/**
* 代理周期
*/
private int period
;
/**
* 代理产品
*/
private int
[
] products
;
public
Agent
(
String name
, String type
)
{
super
(name
, type
)
;
}
}
新增简单工厂类:
新建一个简单工厂,提供一个公共静态方法,根据不同的客户类型创建不同的客户。
/**
* 客户简单工厂
*/
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:
*/
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
)
;
}
}
输出结果:

可以看出简单工厂的使用很简单,就是耦合性太高了。
第一,对象和基类之间是基于继承的。
第二,工厂类耦合了不同对象的创建,如果对象类型不是固定或者经常变动的,就要频繁修改工厂类,比如我现在要再加一种客户,就必须要改动工厂类,不符开闭原则。
所以,简单工厂只适用于固定类型对象的创建。
工厂方法就是为某类产品提供一个工厂接口,然后为每个产品提供一个工厂实现类。
废话少说,我们将简单工厂的示例用工厂方法再改造一下。
新建工厂方法接口:
/**
* 工厂方法客户接口
*/
public
interface
CustomerFactory
{
Customer create
(String type
, String name
)
;
}
新建商户工厂实现类:
/**
* 商户工厂
*/
public
class
MerchantFactory
implements
CustomerFactory
{
@Override
public
Customer create
(
String type
, String name
)
{
return
new
Merchant
(type
, name
)
;
}
}
新建银行客户工厂实现类:
/**
* 银行客户工厂
*/
public
class
BankPartnerFactory
implements
CustomerFactory
{
@Override
public
Customer create
(
String type
, String name
)
{
return
new
BankPartner
(type
, name
)
;
}
}
新建代理商工厂实现类:
/**
* 代理商工厂
*/
public
class
AgentFactory
implements
CustomerFactory
{
@Override
public
Customer create
(
String type
, String name
)
{
return
new
Agent
(type
, name
)
;
}
}
新建测试类:
/**
* @author:
*/
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
)
;
}
}
输出结果:

可以看出,工厂方法也是挺简单易用的,耦合性问题也解决了,每增加一个产品就新增一个产品工厂实现类就行了,扩展性非常好。
但也有一个问题,如果产品非常多,那势必会造成工厂实现类泛滥,另外一种可怕的场景就是,如果涉及到工厂接口变更,工厂实现类的维护简直就是一种恶梦。
工厂方法中一个工厂只能创建一个对象,如果现在每次创建客户的时候都需要同时创建一份客户扩展资料,那就可以考虑使用抽象工厂。
新建客户扩展基类:
/**
* 客户扩展
*/
@Data
@NoArgsConstructor
public abstract
class
CustomerExt
{
/**
* 客户曾用名
*/
private String formerName
;
/**
* 客户扩展说明
*/
private String note
;
}
新建商户扩展类:
/**
* 商户
*/
@Data
@
ToString
(callSuper
=
true
)
public
class
MerchantExt
extends
CustomerExt
{
/**
* 介绍人
*/
private int introduceName
;
/**
* 介绍人电话
*/
private String introduceTel
;
}
新建银行客户扩展类:
/**
* 银行客户扩展
*/
@Data
@
ToString
(callSuper
=
true
)
public
class
BankPartnerExt
extends
CustomerExt
{
/**
* 分行个数
*/
private int branchCount
;
/**
* ATM个数
*/
private int atmCount
;
}
新建代理商扩展类:
/**
* 商户
*/
@Data
@
ToString
(callSuper
=
true
)
public
class
AgentExt
extends
CustomerExt
{
/**
* 来源
*/
private String source
;
/**
* 资质
*/
private String certification
;
}
新建抽象工厂接口:
/**
* 抽象工厂客户接口
*/
public
interface
CustomerFactory
{
Customer createCustomer
(String type
, String name
)
;
CustomerExt createCustomerExt
(
)
;
}
新建商户工厂实现类:
/**
* 商户工厂
*/
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
(
)
;
}
}
新建银行客户工厂实现类:
/**
* 银行客户工厂
*
*/
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
(
)
;
}
}
新建代理商工厂实现类:
/**
* 代理商工厂
*/
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
*java学习交流:737251827 进入可领取学习资源及对十年开发经验大佬提问,免费解答!
*/
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 对象了。
但话又说回来,从示例可以看出,如果使用或者设计不当也会带来维护上的工作量。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70010294/viewspace-2845778/ ,如需转载,请注明出处,否则将追究法律责任。