写点什么

设计模式之工厂模式

作者:乌龟哥哥
  • 2022 年 5 月 10 日
  • 本文字数:3212 字

    阅读完需:约 11 分钟

设计模式之工厂模式

工厂模式可以细分为:简单工厂、工厂方法和抽象工厂三种模式

使用场景

总体而言工厂模式的使用场景分为两种:


  1. 单个对象的创建过程比较复杂,如需要做复杂初始化操作的对象

  2. 需要根据不同的类型创建不同的对象


针对细分的三种模式,使用场景又可以区分:


  1. 对象的创建逻辑简单,通常只需要 new 一下就可以,此时可以考虑简单工厂模式

  2. 对象的创建逻辑很复杂,需要做各种初始化操作,此时可以考虑使用工厂方法模式,将对象创建的复杂逻辑拆分到各个工厂类中,让每个工厂类都不至于过于复杂

  3. 系统中有多于一个产品族,而每次只使用其中某一产品族,此时使用抽象工厂模式

简单工厂模式

类图

ProcuctA 和 ProductB 继承 Product 抽象类,ProductFactory 根据传入的 type 来返回不同的 Product 实例

代码实现

Product

public abstract class Product {    public abstract void use();}
复制代码

ProductA

public class ProductA extends Product {    @Override    public void use() {        System.out.println("You are using ProductA...");    }}
复制代码

ProductB

public class ProductB extends Product {    @Override    public void use() {        System.out.println("You are using ProductB...");    }}
复制代码

ProductFactory

public class ProductFactory {    public Product createProduct(String type) {        Product product = null;        if ("A".equals(type)) {            product = new ProductA();        } else if ("B".equals(type)) {            product = new ProductB();        }        return product;    }}
复制代码

Main

public class Main {    public static void main(String[] args) {        ProductFactory factory = new ProductFactory();        Product product;
product = factory.createProduct("A"); product.use();
product = factory.createProduct("B"); product.use(); }}
复制代码

点评

当频繁的新增不同产品时,需要频繁的修改ProductFactory中的if/else逻辑

应用

JDK


java.text.DateFormat#getDateInstance()java.text.DateFormat#getDateInstance(int)java.text.DateFormat#getDateInstance(int, java.util.Locale)
复制代码


加密类,获取不同加密算法的密钥生成器:


KeyGenerator keyGen=KeyGenerator.getInstance("DESede");
复制代码

工厂方法模式

类图

相比简单工厂,这种方式将ProductFactory定义为抽象类,然后创建不同的具体的ProductAFactoryProductBFactory,在使用时决定创建那种工厂和对象,避免了 if/else 判断

代码实现

Product

public abstract class Product {    public abstract void use();}
复制代码

ProductA

public class ProductA extends Product {    @Override    public void use() {        System.out.println("You are using ProductA...");    }}
复制代码

ProductB

public class ProductB extends Product {    @Override    public void use() {        System.out.println("You are using ProductB...");    }}
复制代码

ProductFactory

public abstract class ProductFactory {    public abstract Product createProduct();}
复制代码

ProductAFactory

public class ProductAFactory extends ProductFactory {    @Override    public Product createProduct() {        return new ProductA();    }}
复制代码

ProductBFactory

public class ProductBFactory extends ProductFactory {    @Override    public Product createProduct() {        return new ProductB();    }}
复制代码

Main

public class Main {
public static void main(String[] args) { ProductFactory factory; Product product;
factory = new ProductAFactory(); product = factory.createProduct(); product.use();
factory = new ProductBFactory(); product = factory.createProduct(); product.use(); }
}
复制代码

点评

这种模式更加符合开闭原则,但是与最原始的new ProductA()new ProductA()相比非常相似,引入工厂模式,反倒让设计变得更加复杂了。

应用

JDBC


Connection conn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db1","db_user","123456");Statement statement=conn.createStatement();ResultSet rs=statement.executeQuery("select * from user");
复制代码

抽象工厂模式

为了理解抽象工厂模式,我们要先了解两个概念:


  • 产品等级结构 :产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL 电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。

  • 产品族 :在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。


在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品。一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

类图

Factory1负责创建ProductA1ProductB1Factory2负责创建ProductA2ProductB2客户端不需要知道具体的产品,只需要知道创建的工厂即可使用该产品

代码实现

AbstractProductA

public abstract class AbstractProductA {
public abstract void use();
}
复制代码

ProductA1

public class ProductA1 extends AbstractProductA {
@Override public void use() { System.out.println("You are using ProductA1..."); }
}
复制代码

ProductA2

public class ProductA2 extends AbstractProductA {
@Override public void use() { System.out.println("You are using ProductA2..."); }
}
复制代码

AbstractProductB

public abstract class AbstractProductB {
public abstract void eat();
}
复制代码

ProductB1

public class ProductB1 extends AbstractProductB {
@Override public void eat() { System.out.println("You are eating ProductB1..."); }
}
复制代码

ProductB2

public class ProductB2 extends AbstractProductB {
@Override public void eat() { System.out.println("You are eating ProductB2..."); }
}
复制代码

AbstractFactory

public abstract class AbstractFactory {
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
复制代码

Factory1

public class Factory1 extends AbstractFactory {
@Override public AbstractProductA createProductA() { return new ProductA1(); }
@Override public AbstractProductB createProductB() { return new ProductB1(); }
}
复制代码

Factory2

public class Factory2 extends AbstractFactory {
@Override public AbstractProductA createProductA() { return new ProductA2(); }
@Override public AbstractProductB createProductB() { return new ProductB2(); }
}
复制代码

Main

public class Main {
public static void main(String[] args) { AbstractFactory factory; factory = new Factory1(); use(factory);
factory = new Factory2(); use(factory); }
public static void use(AbstractFactory factory) { AbstractProductA productA = factory.createProductA(); productA.use(); AbstractProductB productB = factory.createProductB(); productB.eat(); }
复制代码


发布于: 刚刚阅读数: 2
用户头像

乌龟哥哥

关注

正在努力寻找offer的大四小菜鸟 2021.03.16 加入

擅长 Hbuilder、VS Code、MyEclipse、AppServ、PS 等软件的安装与卸载 精通 Html、CSS、JavaScript、jQuery、Java 等单词的拼写 熟悉 Windows、Linux、 等系统的开关机 看–时间过得多快,不说了,去搬砖了

评论

发布
暂无评论
设计模式之工厂模式_5月月更_乌龟哥哥_InfoQ写作社区