书接上回,本篇讲一下创建型模式-简单工厂设计模式
工厂设计模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。目前流行的说法,工厂设计模式有3种:
简单工厂设计模式
目前找不到定义,一个较为认可的说法:简单工厂并不是一个种设计模式,反而比较像一种编程习惯。
工厂方法设计模式
工厂方法设计模式:通过让子类决定该创建对象是什么,来达到将对象创建过程封装的目的。
抽象工厂设计模式
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
本篇重点讲解一下简单工厂设计模式
工厂顾名思义,生产产品的地方,所以工厂模式参与核心角色:产品,工厂,而它的精髓在于:工厂如何科学生产产品。
需求:华为工厂创建华为手机/华为电脑
产品:
//华为商品基类
public abstract class HWProduct {
//商品展示
public abstract void show();
}
//华为手机继承华为商品基类
public class HWPhoneProduct extends HWProduct{
@Override
public void show() {
System.out.println("HWPhone被创建了.....");
}
}
//华为电脑继承华为商品基类
public class HWComputerProduct extends HWProduct{
@Override
public void show() {
System.out.println("HWComputer被创建了.....");
}
}
工厂:
//华为工厂
public class HWProductFactory {
//根据产品类型生成产品
public HWProduct produce(String type){
if("hwphone".equals(type)){
return new HWPhoneProduct();
}else if("hwcomputer".equals(type)){
return new HWComputerProduct();
}
return null;
}
}
客户端:
public class App {
public static void main(String[] args) {
//工厂
HWProductFactory factory = new HWProductFactory();
//手机
HWProduct phone = factory.produce("hwphone");
phone.show();
//电脑
HWProduct computer = factory.produce("hwcomputer");
computer.show();
}
}
分析
简单工厂设计模式就是一种创建对象的编码习惯, 按照传统方式直接使用new就可以啦,引入factory类的目的是隐藏对象new过程细节。观察App类,HWPhoneProduct,HWComputerProduct个对象的创建是通过factory的produce方法,具体对象初始化过程,App类是不需要知道。居于此,简单工厂设计模一般用在需要遮蔽实例构建过程场景。比如:实例初始化操作。
但是,这种代码设计方法存在一定瑕疵啦:违背了开闭原则设计原则(软件实体应当对扩展开放,对修改关闭)。比如:当新增华为平板产品时,就需要变动HWProductFactory类啦,这个改动就犯大忌了。那怎办?可以使用下一篇讲的:工厂方法设计模式。
上面的分析说了,简单工厂方法存在瑕疵,当新增产品时,会违背开闭原则,那它就无用了么?其实不然,下面场景还是可以使用简单工厂设计模式的。
1>工厂类负责创建的对象较少(最好是个数固定)
2>客户端(应用层)关心对象创建结果,不关心创建对象过程
优点:隐藏对象构建细节
只需要传入一个正确的参数,就可以获取你所需要的对象而无须知道其构建细节
缺点:违背开闭原则
工厂类的职责相对过重,增加新产品时需要修改工厂类的判断逻辑,违背开闭原则(扩展放开,修改关闭)
JDK中有很多工厂模式的运用,这里说一个简单的:日历类Calendar
public static Calendar getInstance(){
Locale aLocale = Locale.getDefault(Locale.Category.FORMAT);
return createCalendar(defaultTimeZone(aLocale), aLocale);
}
private static Calendar createCalendar(TimeZone zone, Locale aLocale){
//.....
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
//.......
}
上面代码中,根据传入的Locale参数使用switch语法区分不同地区,然后创建不同的Calendar对象,标准的简单工厂模式。这里可能会有朋友问:这里的工厂是谁, 产品是谁?
工厂:Calendar, 产品:JapaneseImperialCalendar,BuddhistCalendar,GregorianCalendar,而这些产品跟工厂又是子父类关系,那又如何,依然不妨碍它们是标准的简单工厂模式。这里强调:学习设计模式学习其神而不是其形。
1>简单工厂本质是选择实现,创建对象实例根据具体传入决定具体实现。
2>简单工厂设计模式适用场景:创建的对象种类有限的情况下使用
3>设计模式学习其神而不是其形,设计思路不变,而代码表现形式可能有多种