在我们平常创建对象的时候,都是通过关键字 new 来实现的,例: Class A = new A() 。

在一些情况下,要创建的对象需要一系列复杂的初始化操作,比如查配置文件、查数据库表、初始化成员对象等,如果把这些逻辑放在构造函数中,会极大影响代码的可读性。不妨定义一个类来专门负责对象的创建,这样的类就是工厂类,这种做法就是工厂模式,在任何需要生成复杂对象的地方,都可以使用工厂模式。

工厂模式包括:简单工厂(不在23种设计模式中)、工厂方法和抽象工厂。

解决的问题

客户端在调用时不想判断来实例化哪一个类或者实例化的过程过于复杂。

在工厂模式中,具体的实现类创建过程对客户端是透明的,客户端不决定具体实例化哪一个类,而是交由“工厂”来实例化。

简单工厂

▐ 结构
定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类。

image.png

抽象类或接口:定义了要创建的产品对象的接口。

具体实现:具有统一父类的具体类型的产品。

产品工厂:负责创建产品对象。工厂模式同样体现了开闭原则,将“创建具体的产品实现类”这部分变化的代码从不变化的代码“使用产品”中分离出来,之后想要新增产品时,只需要扩展工厂的实现即可。

▐ 使用

创建不同品牌的键盘

public interface Keyboard {
void print();
void input(Context context);
}

class HPKeyboard implements Keyboard {

@Override
public void print() {//...输出逻辑;
}@Override
public void input(Context context) {//...输入逻辑;
}

}

class DellKeyboard implements Keyboard {

@Override
public void print() {//...输出逻辑;
}@Override
public void input(Context context) {//...输入逻辑;
}

}

class LenovoKeyboard implements Keyboard {

@Override
public void print() {//...输出逻辑;
}@Override
public void input(Context context) {//...输入逻辑;
}

}

/**

  • 工厂
    */
    public class KeyboardFactory {
    public Keyboard getInstance(int brand) {
    if(BrandEnum.HP.getCode() == brand){
    return new HPKeyboard();
    } else if(BrandEnum.LENOVO.getCode() == brand){
    return new LenovoKeyboard();
    } else if(BrandEnum.DELL.getCode() == brand){
    return new DellKeyboard();
    }
    return null;
    }

    public static void main(String[] args) {
    KeyboardFactory keyboardFactory = new KeyboardFactory();
    Keyboard lenovoKeyboard = KeyboardFactory.getInstance(BrandEnum.LENOVO.getCode());
    //…
    }

}
▐ 缺陷
上面的工厂实现是一个具体的类KeyboardFactory,而非接口或者抽象类,getInstance()方法利用if-else创建并返回具体的键盘实例,如果增加新的键盘子类,键盘工厂的创建方法中就要增加新的if-else。这种做法扩展性差,违背了开闭原则,也影响了可读性。所以,这种方式使用在业务较简单,工厂类不会经常更改的情况。

工厂方法
为了解决上面提到的"增加if-else"的问题,可以为每一个键盘子类建立一个对应的工厂子类,这些工厂子类实现同一个抽象工厂接口。这样,创建不同品牌的键盘,只需要实现不同的工厂子类。当有新品牌加入时,新建具体工厂继承抽象工厂,而不用修改任何一个类。

▐ 结构

抽象工厂:声明了工厂方法的接口。

具体产品工厂:实现工厂方法的接口,负责创建产品对象。

产品抽象类或接口:定义工厂方法所创建的产品对象的接口。

具体产品实现:具有统一父类的具体类型的产品。

▐ 使用

public interface IKeyboardFactory {
Keyboard getInstance();
}

public class HPKeyboardFactory implements IKeyboardFactory {
@Override
public Keyboard getInstance(){
return new HPKeyboard();
}
}

public class LenovoFactory implements IKeyboardFactory {
@Override
public Keyboard getInstance(){
return new LenovoKeyboard();
}
}

public class DellKeyboardFactory implements IKeyboardFactory {
@Override
public Keyboard getInstance(){
return new DellKeyboard();
}
}
▐ 缺点

每一种品牌对应一个工厂子类,在创建具体键盘对象时,实例化不同的工厂子类。但是,如果业务涉及的子类越来越多,难道每一个子类都要对应一个工厂类吗?这样会使得系统中类的个数成倍增加,增加了代码的复杂度。

抽象工厂

为了缩减工厂实现子类的数量,不必给每一个产品分配一个工厂类,可以将产品进行分组,每组中的不同产品由同一个工厂类的不同方法来创建。

例如,键盘、主机这2种产品可以分到同一个分组——电脑,而不同品牌的电脑由不同的制造商工厂来创建。

image.png

类似这种把产品类分组,组内不同产品由同一工厂类的不同方法实现的设计模式,就是抽象工厂模式。

抽象工厂适用于以下情况:

  1. 一个系统要独立于它的产品的创建、组合和表示时;
  2. 一个系统要由多个产品系列中的一个来配置时;
  3. 要强调一系列相关的产品对象的设计以便进行联合使用时;
  4. 当你提供一个产品类库,而只想显示它们的接口而不是实现时;

▐ 结构
image.png

抽象工厂:声明了创建抽象产品对象的操作接口。

具体产品工厂:实现了抽象工厂的接口,负责创建产品对象。

产品抽象类或接口:定义一类产品对象的接口。

具体产品实现:定义一个将被相应具体工厂创建的产品对象。

▐ 使用

public interface Keyboard {
void print();
}
public class DellKeyboard implements Keyboard {
@Override
public void print() {
//…dell…dell;
}
}
public class HPKeyboard implements Keyboard {
@Override
public void print() {
//…HP…HP;
}
}
public interface Monitor {
void play();
}
public class DellMonitor implements Monitor {
@Override
public void play() {
//…dell…dell;
}
}
public class HPMonitor implements Monitor {
@Override
public void play() {
//…HP…HP;
}
}
public interface MainFrame {
void run();
}
public class DellMainFrame implements MainFrame {
@Override
public void run() {
//…dell…dell;
}
}
public class HPMainFrame implements MainFrame {
@Override
public void run() {
//…HP…HP;
}
}
//工厂类。工厂分为Dell工厂和HP工厂,各自负责品牌内产品的创建
public interface IFactory {
MainFrame createMainFrame();
Monitor createMainFrame();
Keyboard createKeyboard();
}
public class DellFactory implements IFactory {
@Override
public MainFrame createMainFrame(){
MainFrame mainFrame = new DellMainFrame();
//…造一个Dell主机;
return mainFrame;
}

  @Overridepublic Monitor createMonitor(){Monitor monitor = new DellMonitor();//...造一个Dell显示器;return monitor;}@Overridepublic Keyboard createKeyboard(){Keyboard keyboard = new DellKeyboard();//...造一个Dell键盘;return Keyboard;}

}
public class HPFactory implements IFactory {
@Override
public MainFrame createMainFrame(){
MainFrame mainFrame = new HPMainFrame();
//…造一个HP主机;
return mainFrame;
}

  @Overridepublic Monitor createMonitor(){Monitor monitor = new HPMonitor();//...造一个HP显示器;return monitor;}@Overridepublic Keyboard createKeyboard(){Keyboard keyboard = new HPKeyboard();//...造一个HP键盘;return Keyboard;}

}
//客户端代码。实例化不同的工厂子类,可以通过不同的创建方法创建不同的产品
public class Main {
public static void main(String[] args) {
IFactory dellFactory = new DellFactory();
IFactory HPFactory = new HPFactory();
//创建戴尔键盘
Keyboard dellKeyboard = dellFactory.createKeyboard();
//…
}
}
▐ 优缺点
增加分组非常简单,例如要增加Lenovo分组,只需创建Lenovo工厂和具体的产品实现类。分组中的产品扩展非常困难,要增加一个鼠标Mouse,既要创建抽象的Mouse接口, 又要增加具体的实现:DellMouse、HPMouse, 还要再每个Factory中定义创建鼠标的方法实现。

▐ 总结
简单工厂:唯一工厂类,一个产品抽象类,工厂类的创建方法依据入参判断并创建具体产品对象。

工厂方法:多个工厂类,一个产品抽象类,利用多态创建不同的产品对象,避免了大量的if-else判断。

抽象工厂:多个工厂类,多个产品抽象类,产品子类分组,同一个工厂实现类创建同组中的不同产品,减少了工厂子类的数量。

在下述情况下可以考虑使用工厂模式:

在编码时不能预见需要创建哪种类的实例。

系统不应依赖于产品类实例如何被创建、组合和表达的细节。

总之,工厂模式就是为了方便创建同一接口定义的具有复杂参数和初始化步骤的不同对象。工厂模式一般用来创建复杂对象。只需用new就可以创建成功的简单对象,无需使用工厂模式,否则会增加系统的复杂度。

此外,如果对象的参数是不固定的,推荐使用Builder模式。

后记
在实际项目中,结合Spring中的InitializingBean接口,可以利用@Autowired注解优雅的实现工厂。

淘系技术部-行业技术团队-诚招英才

我们是阿里巴巴淘系行业技术团队,负责淘系行业电商业务的增长和创新,支撑着服饰、快消、家装、消电等数十个行业快速发展,日均服务千万用户,产生千亿级GMV。在这里,你可以接触到整个淘系行业的核心业务和技术体系,赋能多个淘宝天猫行业,快速孵化创新业务;在这里,你还可以深入挖掘行业商业化和分销场景,激活行业内各种生态角色,创造电商业务的新增量。

招聘岗位:java开发

如果您有兴趣可发简历至weicleer.lwc@alibaba-inc.com,欢迎来撩~

设计模式学习总结——工厂模式相关推荐

  1. 设计模式 - 学习笔记 - 工厂模式Factory Pattern

    设计模式 - 学习笔记 - 工厂模式Factory Pattern 1. 简单工厂 1.1 应用场景 1.2 UML 1.3 优劣分析 好处 缺点 1.4 代码示例 抽象产品 AbstractProd ...

  2. Java设计模式学习之工厂模式

    简单工厂模式 我直接上代码代码里有很详细的注解 //简单工厂模式 是由一个工厂对象决定创建出哪种产品 class Factory1 {publicstatic void main(String[] a ...

  3. 设计模式学习之工厂模式(附demo)

    介绍 工厂模式(Factory Pattern) 是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客户端暴 ...

  4. 设计模式学习2 工厂模式

    工厂模式其实就是简单模式的升级版本, 简单模式将界面与业务逻辑区分开,但是如果不停的增加计算器的运算方式,简单模式中的工厂Factory 中判断的业务逻辑会变非常复杂,这不符合封装的原则. 所以在此之 ...

  5. Java设计模式学习02——工厂模式

    工厂模式 工厂模式主要是为创建对象提供接口,将创建对象的过程隔离起来,实现了创建者与调用者的分离,提高了程序的灵活性.  核心本质: 实例化对象,用工厂方法代替new操作. 将选择实现类.创建对象统一 ...

  6. 设计模式学习-工厂方法模式

    在上文(设计模式学习-简单工厂模式)的模拟场景中,我们用简单工厂模式实现了VISA和MASTERARD卡的刷卡处理,系统成功上线并运行良好,突然有一天老大跑来说,我们的系统需要升级,提供对一般银联卡的 ...

  7. 一起学习设计模式--02.简单工厂模式

    工厂模式是最常用的一类创建型设计模式.我们所说的工厂模式是指工厂方法模式,它也是使用频率最高的工厂模式. 简单工厂模式是工厂方法模式的小弟,它不属于GoF 23种设计模式,但是在软件开发中应用也颇为频 ...

  8. 设计模式学习笔记——工厂(Factory)模式

    设计模式学习笔记--工厂(Factory)模式 @(设计模式)[设计模式, 工厂模式, factory] 设计模式学习笔记工厂Factory模式 基本介绍 工厂案例 类图 实现代码 framework ...

  9. 【设计模式学习】工厂方法模式

    cpp学习设计模式:工厂方法模式 在学习工厂方法模式之前,先回忆前面学的简单工厂模式: 简单工厂模式就是将对象的创建和逻辑的判断都交给了一个工厂类去做,这样做的优点是客户端不需要知道具体产品类的类名和 ...

最新文章

  1. python画圆简单代码-python实现画圆功能
  2. 如何提高电脑运行速度_电脑运行速度慢的解决方法
  3. zookeeper应用之分布式锁
  4. Android Studio开发基础之Service
  5. 都灵JVM编程语言:使用ANTLR构建高级词法分析器
  6. C语言代码规范(四)命名规则
  7. Java集合框架使用总结
  8. linux 负载高ssh连不上,关于ssh连不上问题的解决方法(必看)
  9. ADS仿真遇到error如何查找原因
  10. Word文件的OpenXML解析(以Python3为例)
  11. 大学生微信小程序项目总结
  12. 订单类 京东快递电子面单接口的使用开发
  13. TalkingData的使用,iOS数据统计
  14. docker stop all containers
  15. 南充一中2021成绩查询高考,2021年南充一中升学率高不高?
  16. uniCloud 云函数
  17. Creator打android包时报Could not resolve all files for configuration ':jcore-react-native:lintClassPath'异
  18. 【FICO系列】SAP FICO模块-财务账期的打开和关闭
  19. nagios二次开发(四)---nagios监控原理和nagios架构简介
  20. 新天龙官网服务器更新消息,《经典怀旧·新天龙八部》8月5日全服更新维护公告...

热门文章

  1. 用Python批量修改图片名称(后缀)
  2. 从零开始学Pytorch(五)之欠拟合和过拟合
  3. 全攻略:大病医疗专项附加扣除,一文集全了
  4. 使用python写程序时遇到的几个小问题
  5. unity3d android assets,Unity3D之Android同步方法读取streamingAssets(八十八)
  6. mysql 主从热备份 5.6 参数_MySQL主从热备份
  7. 主题图标_iPhone一键更换主题、图标神器
  8. 【快速入门Linux】5_Linux命令—远程管理常用命令
  9. 自动化C语言第一次月考试卷,计算机专业第一次月考.doc
  10. orgmode导出html,含有python代码块的ORG-MODE导出为HTML时出错