Java设计模式-简单工厂模式 - Go语言中文社区

Java设计模式-简单工厂模式


模式内容

简单工厂模式又被称为静态模式,其实现简单,实现过程基本遵循如下过程:

  1. 建立产品接口;
  2. 具体化产品类;
  3. 定义简单工厂,并定义静态方法,生产所有对象。

但是严格意义来说,简单工厂模式并不算一个真正的"设计模式"。

The Simple Factory isn’t actually a Design Pattern; it’s more of a programing idiom. But it is commonly used, so we’ll give it a Head First Pattern Honorable Mention.

在Head First原书中,有上述的提及,说明简单工厂只是一种被开发人员所普遍使用的编程风格。

但是我们还是简单地介绍一下该模式,首先其类图如下:

简单工厂模式

从类图中我们可以看到,有一个产品接口,并派生了两个具体产品ProductAProductB,而工厂的职责便是负责生产这些产品,我们可以有如下的实现。

接口类:

public interface Product {
  public void doSomeThing();
}

产品A类:

public class ProductA implements Pruduct {
  public void doSomeThing() {
    System.out.println("A do...");
  }
}

产品B类:

public class ProductB implements Pruduct {
  public void doSomeThing() {
    System.out.println("B do...");
  }
} 

工厂类:

public ProductFactory {
  public static Product produceProduct(String name) {
    if ("A".equals(name)) {
      return new ProductA();
    } else if ("B".equals(name)) {
      return new ProductB();
    }
  }
}

客户端类:

public class SimpleFactoryClient {

	public static void main(String[] args) {
		Product product = ProductFactory.produceProduct("A");
		product.doSomeThing();
		product = ProductFactory.produceProduct("B");
		product.doSomeThing();
	}
}

通过上述代码,即可使用工厂快速通过参数的不同,动态地获取到不同的产品,并使用产品的方法。

从实现中我们可以看出,对于产品类而言,其具体的创建过程交给了工厂,而客户端在获得产品时,不再需要手动地new创建对象,而时根据产品名称动态地获取到所需要的产品,因此简单工厂能够将对象的创建过程和对象的使用过程隔离

在Head First中,其使用了Pizza的例子,对简单工厂模式进行说明举例。

在这里插入图片描述

该例子也说明了简单工厂的具体模式,不同的是在该类图中依赖关系将其画到了SimplePizzaFactoryPizza之间,但其意义相同。

JDK中的简单工厂

public class DateFormateTest {

	public static void main(String[] args) {
		DateFormat format = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT);
		String now = format.format(new Date());
		System.out.println(now);
	}
	
}

通过使用DateFormat format = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT);可以快速获得一个DateFormat对象,而只需要提供DateStyleTimeStyle,这便是一个简单工厂模式的应用,在JDK中,DateFormat为一个抽象类,而其子类有SimpleDateFormat类,但通过使用简单工厂,仅需要指定style即可获得格式化类,客户端无需关心具体的格式化类是什么。

不仅如此,在JDK加密算法的实现中,也使用了简单工厂。

public class CipherTest {

	public static void main(String[] args) {
		try {
			KeyGenerator aes = KeyGenerator.getInstance("AES");
			SecretKey secKey = aes.generateKey();
			Cipher cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.ENCRYPT_MODE, secKey);
			byte[] encoded = cipher.doFinal("Hello World".getBytes("utf-8"));
			System.out.println(new String(encoded, "utf-8"));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
}

适用场景

  • 工厂类需要负责的产品类有限,且产品的数量变化不大;
  • 客户端不清楚所需对象的细节,只知道对象的具体名称和使用方式。

优缺点

优点:

  • 使用简单工厂可以将产品的创建过程和使用过程隔离,使得使用者无需关注产品的内部结构和创建细节;
  • 结合使用配置文件,可以在不修改代码的情况下,动态地修改系统中使用的类(这对于框架设计来说是一个很重要的方式,配置文件为使用者提供了替换和选择相关组件的能力);
  • 将客户端与各个产品解耦,减少类的依赖。

缺点:

  • 在工厂类会创建所有产品,当产品增加时,工厂类方法内部需要更改以适配新的产品,破坏了"开闭原则";
  • 不适合产品过多,且产品数量经常变化的情形,过多的产品将导致工厂内部逻辑复杂混乱。

上述代码可访问Github获取。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/zouzhipeng1717/article/details/88973586
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 21:38:12
  • 阅读 ( 1118 )
  • 分类:设计模式

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢