设计模式——工厂模式
Posted 唐杠杠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式——工厂模式相关的知识,希望对你有一定的参考价值。
设计模式——工厂模式
首先不是写给萌新看的,观看前需要有javaSE的基础。文采、绘画水平不佳,还请担待。
工厂模式
主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提供灵活性的目的。
简单工厂模式
-
主要角色:
-
工厂类角色:本模式的核心,在java中往往由一个具体类实现
-
抽象产品角色:一般是具体产品继承或者实现的接口,在java中由接口或者抽象类来实现
-
具体产品:工厂类所创建的对象就是此角色的实例
-
逻辑如下:
简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。
目的:它存 在的目的很简单:定义一个用于创建对象的接口。
-
代码如下
import java.util.Random; /** *工厂类 */ public class SimpleFactor { public static void main(String[] args) { Phone phone = makePhone(); phone.describe(); } public static Phone makePhone() { Random random = new Random(); int i = random.nextInt(); if (i % 2 == 0) { return new MiPhone(); } else { return new IPhone(); } } } /** * 抽象产品角色 */ interface Phone { void describe(); } /** * 具体产品 */ class MiPhone implements Phone { @Override public void describe() { System.out.println("小米手机进击高端市场了"); } } /** * 具体产品 */ class IPhone implements Phone { @Override public void describe() { System.out.println("苹果手机信号不好"); } }
-
优缺点
优点:
-
将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,实现了解耦;
-
把初始化实例时的工作放到工厂里进行,使代码更容易维护。 更符合面向对象的原则 & 面向接口编程,而不是面向实现编程。
缺点:
-
工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;
-
违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。
-
简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。
-
工厂方法模式
-
主要角色
- 抽象工厂:提供创建产品的接口,调用者通过它访问具体工厂的工厂方法
- 具体工厂:实现抽象工厂的方法,完整自己具体产品的创建
- 抽象产品:定义产品的规范
- 具体产品:实现抽象产品的方法,由具体工程来创建对应的产品
-
逻辑如下:
和简单工厂模式(工厂负责生产所有的产品)相比,工厂方式模式将具体产品的任务分发给具体的产品工厂。
目的:也就是说定义了一个抽象工厂,其定义了产品的生产接口,但是不负责具体的产品,将具体任务分给具体的工厂
- 代码如下:
import java.util.Random; /** * 抽象工厂 */ interface MakeCar { Car make(); } /** * 抽象产品 */ interface Car { void descar(); } /** * 具体工厂1 */ class BenzMake implements MakeCar { @Override public Car make() { System.out.println("开始制造奔驰"); return new BenzCar(); } } /** * 具体工厂2 */ class BmwMake implements MakeCar { @Override public Car make() { System.out.println("开始制造宝马"); return new BMWCar(); } } /** * 具体产品1 */ class BenzCar implements Car { @Override public void descar() { System.out.println("奔驰大标好"); } } /** * 具体产品2 */ class BMWCar implements Car { @Override public void descar() { System.out.println("宝马操控性好"); } } /** * 调用 */ public class Factory { public static void main(String[] args) { int i = new Random().nextInt(10); MakeCar make = null; if (i % 2 == 0) { //指定具体的工厂来制造 make = new BenzMake(); } else { //指定具体的工厂来制造 make = new BmwMake(); } //得到具体的产品 Car car = make.make(); //产品的特点 car.descar(); } }
-
优缺点
优点:
-
更符合开-闭原则
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可> 简单工厂模式需要修改工厂类的判断逻辑
-
符合单一职责原则
每个具体工厂类只负责创建对应的产品> 简单工厂中的工厂类存在复杂的switch逻辑判断
-
不使用静态工厂方法,可以形成基于继承的等级结构。
> 简单工厂模式的工厂类使用静态工厂方法
总结:工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
缺点:
-
添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
-
由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
-
虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;
-
一个具体工厂只能创建一种具体产品
-
抽象工厂模式
上面两种模式不管工厂怎么拆分抽象,都只是针对一类产品,如果要生产另外一种产品,该怎么办?
先来认识下产品族:
宝马的跑车,奔驰的跑车,都可以归类到跑车产品,而这个跑车产品就是一个产品族。
抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是最为抽象,最具一般性的
目的:给客户提供一个接口,可以创建多个产品族中的产品对象,而且使用抽象工厂还要满足以下条件:
-
系统中有多个产品族,而系统一次只可能消费其中一族产品。
-
同属于一个产品族的产品以其使用。
-
主要角色
- 抽象工厂角色:这是工厂方法模式的核心,与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类
- 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
- 抽象产品角色:它是由具体产品继承的父类或者实现的接口。
- 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
-
逻辑如下
抽象产品A、抽象产品B 表示一个产品族(比如下面例子中的手表、随身听),具体工厂1、具体工厂2 就表示一个厂牌的工厂(比如下面例子的小米工厂、sony工厂),那么就简单了,小米工厂生产手表,随身听;sony工厂也可以生产手表,随身听
-
代码如下
package com.yx.design_mod.factory.simple; /** * 抽象工厂 */ interface FactoryUnionAll { Watch makeWatch(); Walkman makeWalkMan(); } /** * 抽象产品1 */ interface Watch { void showTime(); } /** * 抽象产品2 */ interface Walkman { void playMusic(); } /** * 具体工厂1 */ class MibranFactory implements FactoryUnionAll { @Override public Watch makeWatch() { System.out.println("开始制造小米手表"); return new MiWatch(); } @Override public Walkman makeWalkMan() { System.out.println("开始制造小米随身听"); return new MiWalkman(); } } /** * 具体工厂2 */ class SonyFactory implements FactoryUnionAll { @Override public Watch makeWatch() { System.out.println("开始制造sony手表"); return new SonyWatch(); } @Override public Walkman makeWalkMan() { System.out.println("开始制造sony随身听"); return new SonyWalkMan(); } } /** * 具体产品1 */ class MiWatch implements Watch { @Override public void showTime() { System.out.println("小米滴滴滴"); } } /** * 具体产品2 */ class SonyWatch implements Watch { @Override public void showTime() { System.out.println("sony 哒哒哒"); } } class MiWalkman implements Walkman { @Override public void playMusic() { System.out.println("小米音乐卡卡卡"); } } class SonyWalkMan implements Walkman { @Override public void playMusic() { System.out.println("sony nb"); } } /** * @author :tangfan * @date :Created in 2020/8/5 15:20 * @description: * @modified By: */ public class AbstractFactory { public static void main(String[] args) { FactoryUnionAll mibranFactory = new MibranFactory(); FactoryUnionAll sonyFactory = new SonyFactory(); mibranFactory.makeWalkMan().playMusic(); mibranFactory.makeWatch().showTime(); sonyFactory.makeWatch().showTime(); sonyFactory.makeWalkMan().playMusic(); } }
-
优缺点
优点:
-
降低耦合
抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展; -
更符合开-闭原则
新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可> 简单工厂模式需要修改工厂类的判断逻辑
-
符合单一职责原则
每个具体工厂类只负责创建对应的产品> 简单工厂中的工厂类存在复杂的switch逻辑判断
-
不使用静态工厂方法,可以形成基于继承的等级结构。
> 简单工厂模式的工厂类使用静态工厂方法
缺点:
抽象工厂模式很难支持新种类产品的变化。
这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。 -
-
以上是关于设计模式——工厂模式的主要内容,如果未能解决你的问题,请参考以下文章
设计模式简单工厂模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )