工厂方法(Factory Method)模式:
1. 简单工厂模式
- 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
- 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
1.1.1意图
- 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
1.1.2主要解决
主要解决接口选择的问题。
1.1.3何时使用
我们明确地计划不同条件下创建不同实例时。
1.1.4如何解决
让其子类实现工厂接口,返回的也是一个抽象的产品。
1.1.5关键代码
创建过程在其子类执行。
1.1.6应用实例
- 您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
- Hibernate 换数据库只需换方言和驱动就可以。
1.1.7优点
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
1.1.8缺点
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,
在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
1.1.9使用场景
- 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
- 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
- 设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。
1.1.10注意事项
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。
有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要
1.1.11代码示例(未用工厂模式前)
package com.xql.designpattern.controller.factory;
/**
* @author
* @date 2022/08/18 08:07
**/
public class PizzeStore {
public static void main(String[] args) {
new OrderPizza("Greek");
new OrderPizza("Cheese");
new OrderPizza("1");
}
}
package com.xql.designpattern.controller.factory;
import java.util.Objects;
/**
* 订购披萨渠道1
*
* @author
* @date 2022/08/18 08:04
**/
public class OrderPizza {
private String type;
public OrderPizza(String type) {
Pizza pizza = null;
if ("Greek".equals(type)){
pizza = new GreekPizza();
pizza.setName("披萨类型1");
}else if ("Cheese".equals(type)){
pizza = new CheesePrizza();
pizza.setName("披萨类型2");
}
if (Objects.isNull(pizza)){
System.out.println("无当前种类");
return;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
package com.xql.designpattern.controller.factory;
public abstract class Pizza {
protected String name;
public abstract void prepare();
public void bake() {
System.out.println(name + " baking;");
}
public void cut() {
System.out.println(name + " cutting;");
}
public void box() {
System.out.println(name + " boxing;");
}
public void setName(String name) {
this.name = name;
}
}
package com.xql.designpattern.controller.factory;
/**
* 披萨类型2
*
* @author 许清磊
* @date 2022/08/18 08:01
**/
public class CheesePrizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备披萨类型2的材料");
}
}
package com.xql.designpattern.controller.factory;
/**
* 披萨类型1
*
* @author 许清磊
* @date 2022/08/18 08:01
**/
public class GreekPizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备披萨类型1的材料");
}
}
1.12代码示例(1.简单工厂模式-非静态)
package com.xql.designpattern.controller.factory;
/**
* @author
* @date 2022/08/18 08:07
**/
public class PizzeStore {
public static void main(String[] args) {
new OrderPizza(new SimpleFactory());
new OrderPizza(new SimpleFactory());
new OrderPizza(new SimpleFactory());
}
}
package com.xql.designpattern.controller.factory;
import java.util.Objects;
/**
* 订购披萨渠道1
*
* @author
* @date 2022/08/18 08:04
**/
public class OrderPizza {
private SimpleFactory simpleFactory;
public OrderPizza(SimpleFactory simpleFactory) {
setSimpleFactory(simpleFactory);
}
public void setSimpleFactory(SimpleFactory simpleFactory) {
this.simpleFactory = simpleFactory;
Pizza bean = simpleFactory.getBean("Cheese");
if (Objects.nonNull(bean)){
bean.prepare();
bean.bake();
bean.cut();
bean.box();
}
}
}
package com.xql.designpattern.controller.factory;
/**
* 披萨工厂
*
* @author
* @date 2022/08/18 08:14
**/
public class SimpleFactory {
public Pizza getBean(String type){
Pizza pizza = null;
if ("Greek".equals(type)){
pizza = new GreekPizza();
pizza.setName("披萨类型1");
}else if ("Cheese".equals(type)){
pizza = new CheesePrizza();
pizza.setName("披萨类型2");
}
return pizza;
}
}
1.1.13代码示例(1.简单工厂模式-静态)
package com.xql.designpattern.controller.factory;
/**
* @author
* @date 2022/08/18 08:07
**/
public class PizzeStore {
public static void main(String[] args) {
new OrderPizza();
new OrderPizza();
new OrderPizza();
}
}
package com.xql.designpattern.controller.factory;
import java.util.Objects;
/**
* 订购披萨渠道1
*
* @author
* @date 2022/08/18 08:04
**/
public class OrderPizza {
public OrderPizza() {
setSimpleFactory();
}
public void setSimpleFactory() {
Pizza bean = SimpleFactory.getBean("Cheese");
if (Objects.nonNull(bean)){
bean.prepare();
bean.bake();
bean.cut();
bean.box();
}
}
}
package com.xql.designpattern.controller.factory;
/**
* 披萨工厂
*
* @author
* @date 2022/08/18 08:14
**/
public class SimpleFactory {
public static Pizza getBean(String type){
Pizza pizza = null;
if ("Greek".equals(type)){
pizza = new GreekPizza();
pizza.setName("披萨类型1");
}else if ("Cheese".equals(type)){
pizza = new CheesePrizza();
pizza.setName("披萨类型2");
}
return pizza;
}
}
1.1.4小结
可以发现改善代码后,披萨店铺直接下单,订单去从工厂提货,假如我们现在新增产品,只需要扩展工厂里面的类即可,耦合度也大大降低。
- 简单工厂模式是属于创建型模式,是工厂模式的一-种。简单工厂模式是由一个工厂对象决定创建出哪-种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
- 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
- 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式.
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
2. 工厂方法模式
2.1需要分析
2.2代码实现
package com.xql.designpattern.controller.factory;
public class PizzaStore {
public static void main(String[] args) {
String loc = "bj";
if (loc.equals("bj")) {
//创建北京口味的各种Pizza
new BJOrderPizza();
} else {
//创建伦敦口味的各种Pizza
new LDOrderPizza();
}
// TODO Auto-generated method stub
}
}
package com.xql.designpattern.controller.factory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public abstract class OrderPizza {
//定义一个抽象方法,createPizza , 让各个工厂子类自己实现
abstract Pizza createPizza(String orderType);
// 构造器
public OrderPizza() {
Pizza pizza = null;
String orderType; // 订购披萨的类型
do {
orderType = getType();
pizza = createPizza(orderType); //抽象方法,由工厂子类完成
//输出pizza 制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
package com.xql.designpattern.controller.factory;
public class BJOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new BJCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
// TODO Auto-generated method stub
return pizza;
}
}
package com.xql.designpattern.controller.factory;
public class LDOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new LDPepperPizza();
}
// TODO Auto-generated method stub
return pizza;
}
}
package com.xql.designpattern.controller.factory;
public class LDCheesePizza extends Pizza{
@Override
public void prepare() {
// TODO Auto-generated method stub
setName("伦敦的胡椒pizza");
System.out.println(" 伦敦的胡椒pizza 准备原材料");
}
}
package com.xql.designpattern.controller.factory;
//将Pizza 类做成抽象
public abstract class Pizza {
protected String name; //名字
//准备原材料, 不同的披萨不一样,因此,我们做成抽象方法
public abstract void prepare();
public void bake() {
System.out.println(name + " baking;");
}
public void cut() {
System.out.println(name + " cutting;");
}
//打包
public void box() {
System.out.println(name + " boxing;");
}
public void setName(String name) {
this.name = name;
}
}
package com.xql.designpattern.controller.factory;
public class LDPepperPizza extends Pizza{
@Override
public void prepare() {
// TODO Auto-generated method stub
setName("伦敦的奶酪pizza");
System.out.println(" 伦敦的奶酪pizza 准备原材料");
}
}
package com.xql.designpattern.controller.factory;
public class BJCheesePizza extends Pizza {
@Override
public void prepare() {
// TODO Auto-generated method stub
setName("北京的胡椒pizza");
System.out.println(" 北京的胡椒pizza 准备原材料");
}
}
package com.xql.designpattern.controller.factory;
public class BJPepperPizza extends Pizza {
@Override
public void prepare() {
setName("北京的奶酪pizza");
System.out.println(" 北京的奶酪pizza 准备原材料");
}
}
3.结合源码分析
JDK中的Calendar类中,就使用了简单工厂模式
Calendar calendar = Calendar.getInstance();
Calendar calendar1 = Calendar.getInstance(TimeZone.getDefault());
Calendar calendar2 = Calendar.getInstance(TimeZone.getDefault(), Locale.CANADA);
public static Calendar getInstance()
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
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;
}
}
}