使用Java语言编写设计模式-5.创建型模式-简单工厂模式(Gof之外)
原创2022年9月8日大约 7 分钟约 2111 字
5.创建型模式-简单工厂模式(Gof之外)
5.1.章节内容概述
本章节涉及主要内容有:
5.1.章节内容概述
5.2.章节内容大纲
5.3.简介
5.4.应用场景
5.5.优缺点
5.6.角色及其职责
5.7.模型
5.8.示例
5.9.在开源框架中的应用
5.9.1.在JDK中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。
5.2.章节内容大纲
5.3.简介
简单工厂模式(SimpleFactory Pattern)是一种创建型设计模式,是设计模式中最为常见的模式之一,但是不是Gof提出的23中设计模式中的一种,更像是一种编程习惯。简单工厂模式是隐藏对象的实例化过程,对外部提供一个获取对象的方法,可以根据参数获取不同类型的对象,是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
5.4.应用场景
a.客户端如果只知道传入工厂类得参数,对于如何创建对象得逻辑不关心时
b.客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应得参数
c.工厂负责创建的类少,同时系统中需要的new对象较多而且复杂时可以使用,这样一方面不会造成工厂方法中得业务逻辑太过复杂,另一方面在使用时不用一直new,直接从工厂中获取即可
5.5.优缺点
5.5.1.优点
a.屏蔽了具体的创建逻辑,客户端只需要要传入一个参数即可获取相应的结果,在一定程度上简化了对象的创建过程
b.将实例创建过程和使用过程分离开来,实现了解耦
5.5.2.缺点
a.工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响
b.违背OCP原则,一旦添加新产品就不得不修改工厂类得逻辑,这样就会造成工厂逻辑过于复杂
c.简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构
5.6.角色及其职责
Factory(工厂)
核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
Product(抽象类产品)
工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
ConcreteProduct(具体产品)
简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例,它要实现抽象产品中声明的抽象方法(有关抽象类)
5.7.模型
5.7.1.模型类图
模型类图(有Client)
模型类图(无Client)
5.7.2.模型代码
Product.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;
/**
* Product(抽象产品)
*/
public abstract class Product {
}
ConcreteProductA.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;
/**
* ConcreteProductA(具体产品A)
*/
public class ConcreteProductA extends Product {
}
ConcreteProductB.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;
/**
* ConcreteProductB(具体产品B)
*/
public class ConcreteProductB extends Product {
}
ConcreteProductC.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;
/**
* ConcreteProductC(具体产品C)
*/
public class ConcreteProductC extends Product {
}
Factory.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;
/**
* Factory(简单工厂)
*/
public class Factory {
/**
* 通过工厂方法生产产品
* @param productType
* @return
*/
public Product factoryMethod(String productType) {
Product product = null;
if (productType.equals("productA")) {
product = new ConcreteProductA();
} else if (productType.equals("productB")) {
product = new ConcreteProductB();
} else if (productType.equals("productC")) {
product = new ConcreteProductC();
}
return product;
}
/**
* 调用工厂方法的方法
* @param productType
*/
public void operate(String productType){
Product product = factoryMethod(productType);
System.out.println(product);
}
}
Client.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;
import org.junit.Test;
/**
* Client(客户端)
*/
public class Client {
@Test
public void fun() {
Factory factory = new Factory();
//生产产品A
Product productA = factory.factoryMethod("productA");
System.out.println(productA);
//在工厂中直接调用工厂方法
factory.operate("productA");
System.out.println("--------------------");
//生产产品B
Product productB = factory.factoryMethod("productB");
System.out.println(productB);
//在工厂中直接调用工厂方法
factory.operate("productB");
System.out.println("--------------------");
//生产产品C
Product productC = factory.factoryMethod("productC");
System.out.println(productC);
//在工厂中直接调用工厂方法
factory.operate("productC");
}
}
5.8.示例
5.8.1.不使用简单工厂模式
5.8.1.1.类图
类图(有Client)
类图(无Client)
5.8.1.2.代码
Pizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;
import java.util.ArrayList;
public abstract class Pizza {
protected String name;
protected String dough;
protected String sauce;
protected ArrayList<String> toppings = new ArrayList<String>();
public void prepare() {
System.out.println("preparing..." + this.name);
}
public void bake() {
System.out.println("baking..." + this.name);
}
public void cut() {
System.out.println("cutting..." + this.name);
}
public void box() {
System.out.println("boxing..." + this.name);
}
@Override
public String toString() {
StringBuilder pizza = new StringBuilder();
pizza.append("------" + name + "------\n");
pizza.append("dough:" + dough + "\n");
pizza.append("sauce:" + sauce + "\n");
pizza.append("toppings:\n");
for(String topping:toppings) {
pizza.append(topping+"\n");
}
return String.valueOf(pizza);
}
}
CheesePizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;
public class CheesePizza extends Pizza {
public CheesePizza() {
name = "Cheese Pizza";
dough = "Regular Crust";
sauce = "Marinara Pizza Sauce";
toppings.add("Fresh Mozzarella");
toppings.add("Parmesan");
}
}
ClamPizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;
public class ClamPizza extends Pizza {
public ClamPizza() {
name = "Clam Pizza";
dough = "Thin crust";
sauce = "White garlic sauce";
toppings.add("Clams");
toppings.add("Grated parmesan cheese");
}
}
PepperoniPizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;
public class PepperoniPizza extends Pizza {
public PepperoniPizza() {
name = "Pepperoni Pizza";
dough = "Crust";
sauce = "Marinara sauce";
toppings.add("Sliced Pepperoni");
toppings.add("Sliced Onion");
toppings.add("Grated parmesan cheese");
}
}
PizzaStore.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;
public class PizzaStore {
public Pizza orderPizza(Pizza pizza) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
Client.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;
import org.junit.Test;
public class Client {
@Test
public void fun() {
PizzaStore pizzaStore = new PizzaStore();
Pizza cheesePizza = pizzaStore.orderPizza(new CheesePizza());
System.out.println(cheesePizza);
Pizza pepperoniPizza = pizzaStore.orderPizza(new PepperoniPizza());
System.out.println(pepperoniPizza);
Pizza clamPizza = pizzaStore.orderPizza(new ClamPizza());
System.out.println(clamPizza);
}
}
5.8.2.使用简单工厂模式
5.8.2.1.类图
类图(有Client)
类图(无Client)
5.8.2.2.代码
Pizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;
import java.util.ArrayList;
public abstract class Pizza {
protected String name;
protected String dough;
protected String sauce;
protected ArrayList<String> toppings = new ArrayList<String>();
public void prepare() {
System.out.println("preparing..." + this.name);
}
public void bake() {
System.out.println("baking..." + this.name);
}
public void cut() {
System.out.println("cutting..." + this.name);
}
public void box() {
System.out.println("boxing..." + this.name);
}
@Override
public String toString() {
StringBuilder pizza = new StringBuilder();
pizza.append("------" + name + "------\n");
pizza.append("dough:" + dough + "\n");
pizza.append("sauce:" + sauce + "\n");
pizza.append("toppings:\n");
for(String topping:toppings) {
pizza.append(topping+"\n");
}
return String.valueOf(pizza);
}
}
CheesePizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;
public class CheesePizza extends Pizza{
public CheesePizza() {
name = "Cheese Pizza";
dough = "Regular Crust";
sauce = "Marinara Pizza Sauce";
toppings.add("Fresh Mozzarella");
toppings.add("Parmesan");
}
}
ClamPizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;
public class ClamPizza extends Pizza{
public ClamPizza() {
name = "Clam Pizza";
dough = "Thin crust";
sauce = "White garlic sauce";
toppings.add("Clams");
toppings.add("Grated parmesan cheese");
}
}
PepperoniPizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;
public class PepperoniPizza extends Pizza{
public PepperoniPizza() {
name = "Pepperoni Pizza";
dough = "Crust";
sauce = "Marinara sauce";
toppings.add("Sliced Pepperoni");
toppings.add("Sliced Onion");
toppings.add("Grated parmesan cheese");
}
}
PizzaStoreFactory.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;
public class PizzaStoreFactory {
/**
* 通过工厂方法生产产品
* @param pizzaType
* @return
*/
public Pizza createPizza(String pizzaType) {
Pizza pizza = null;
if (pizzaType.equals("cheese")) {
pizza = new CheesePizza();
} else if (pizzaType.equals("pepperoni")) {
pizza = new PepperoniPizza();
} else if (pizzaType.equals("clam")) {
pizza = new ClamPizza();
}
return pizza;
}
/**
* 调用工厂方法的方法
* @param pizzaType
* @return
*/
public Pizza orderPizza(String pizzaType) {
Pizza pizza = createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
Client.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;
import org.junit.Test;
public class Client {
@Test
public void fun() {
PizzaStoreFactory pizzaFactory = new PizzaStoreFactory();
Pizza cheesePizza = pizzaFactory.orderPizza("cheese");
System.out.println(cheesePizza);
Pizza pepperoniPizza = pizzaFactory.orderPizza("pepperoni");
System.out.println(pepperoniPizza);
Pizza clamPizza = pizzaFactory.orderPizza("clam");
System.out.println(clamPizza);
}
}
5.9.在开源框架中的应用
5.9.1.在JDK中的应用
JDK8#java.util.Calendar
说明
其中的createCalendar()方法根据传入参数的不同创建出不同的Calendar抽象类的子类,也就是根据传入参数的不同创建出了不同的对象,对调用这个方法的方法而言,屏蔽了具体的创建过程,只需要传入参数即可获取对象,符合简单工厂模式要求
类图
代码
public abstract class Calendar {
public static Calendar getInstance()
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
public static Calendar getInstance(TimeZone zone)
{
return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
}
public static Calendar getInstance(Locale aLocale)
{
return createCalendar(TimeZone.getDefault(), aLocale);
}
public static Calendar getInstance(TimeZone zone,
Locale aLocale)
{
return createCalendar(zone, aLocale);
}
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
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;
}
}
}
if (cal == null) {
// If no known calendar type is explicitly specified,
// perform the traditional way to create a Calendar:
// create a BuddhistCalendar for th_TH locale,
// a JapaneseImperialCalendar for ja_JP_JP locale, or
// a GregorianCalendar for any other locales.
// NOTE: The language, country and variant strings are interned.
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
...
}
可以看出,在getInstance()方法中调用了createCalendar()方法,只需要传入zone, aLocale,就可以获得一个Calendar对象
评论