工厂模式介绍
工厂模式属于设计模式中的创建型模式。工厂模式提供了一种最佳的创建对象的方式。工厂模式从简单到复杂有三种:简单工厂、工厂方法、抽象工厂。
举例
从一个奶酪的制作到订购的例子开始分析,我们需要集成披萨制作流程,并且声明出披萨的种类。然后再有订购的流程,先写一个不使用设计模式的例子。
package com.lesson4.factory.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:36
*/
public abstract class Pizza
{
protected String name;
public void setName(String name)
{
this.name = 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;");
}
}
准备两种pizza
package com.lesson4.factory.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:40
*/
public class GreekPizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("给希腊披萨准备原材料");
}
}
package com.lesson4.factory.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:39
*/
public class CheesePizza extends Pizza
{
@Override
public void prepare()
{
System.out.println("准备奶酪原材料");
}
}
订购pizza
package com.lesson4.factory.pizzastore.order;
import com.lesson4.factory.pizzastore.pizza.CheesePizza;
import com.lesson4.factory.pizzastore.pizza.GreekPizza;
import com.lesson4.factory.pizzastore.pizza.Pizza;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:42
*/
public class OrderPizza
{
public OrderPizza()
{
Pizza pizza = null;
String orderType;
do{
orderType = getType();
if(orderType.equals("greek")){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if(orderType.equals("cheese")){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
} else {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}while (true);
}
private String getType(){
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String line = reader.readLine();
return line;
} catch (IOException e)
{
e.printStackTrace();
return "";
}
}
}
客户端
package com.lesson4.factory.pizzastore.order;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:51
*/
public class PizzaStore
{
public static void main(String[] args)
{
new OrderPizza();
}
}
从上面这个例子可以分析,没有使用设计模式他的优势在于简单,但是劣势在于耦合度太高,而且在OrderPizza类中可能会存在大量判断的现象。
简单工厂模式
-
简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
-
简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
-
在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式
对上面的代码进行部分修改,添加SimpleFactory
package com.lesson4.factory.pizzastore.order;
import com.lesson4.factory.pizzastore.pizza.CheesePizza;
import com.lesson4.factory.pizzastore.pizza.GreekPizza;
import com.lesson4.factory.pizzastore.pizza.Pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 14:31
*/
public class SimpleFactory
{
public Pizza createPizza(String orderType){
Pizza pizza = null;
if(orderType.equals("greek")){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if(orderType.equals("cheese")){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}
return pizza;
}
}
OrderPizza修改
package com.lesson4.factory.pizzastore.order;
import com.lesson4.factory.pizzastore.pizza.Pizza;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:42
*/
public class OrderPizza
{
public OrderPizza(SimpleFactory simpleFactory)
{
setSimpleFactory(simpleFactory);
}
SimpleFactory simpleFactory;
Pizza pizza = null;
public void setSimpleFactory(SimpleFactory simpleFactory)
{
String orderType = "";
this.simpleFactory = simpleFactory;
do
{
orderType = getType();
pizza = this.simpleFactory.createPizza(orderType);
if (pizza != null)
{
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else
{
System.out.println("订购失败!");
}
} while (true);
}
private String getType()
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String line = reader.readLine();
return line;
} catch (IOException e)
{
e.printStackTrace();
return "";
}
}
}
工厂方法模式
首先依然定义一个抽象的Pizza类
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:36
*/
public abstract class Pizza
{
protected String name;
public void setName(String name)
{
this.name = 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;");
}
}
然后出四种口味pizza
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:23
*/
public class BJCheesePizza extends Pizza
{
@Override
public void prepare()
{
setName("北京奶酪pizza");
System.out.println("给北京奶酪pizza准备原材料");
}
}
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:26
*/
public class BJHuJiaoPizza extends Pizza
{
@Override
public void prepare()
{
setName("北京胡椒pizza");
System.out.println("给北京胡椒pizza准备原材料");
}
}
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:28
*/
public class LDCheesePizza extends Pizza
{
@Override
public void prepare()
{
setName("伦敦奶酪pizza");
System.out.println("给伦敦奶酪pizza准备原材料");
}
}
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:27
*/
public class LDHujiaoPizza extends Pizza
{
@Override
public void prepare()
{
setName("伦敦胡椒pizza");
System.out.println("给伦敦胡椒pizza准备原材料");
}
}
然后是准备订购pizza,这边也是写个抽象类,构造方法写他的实现逻辑
package com.lesson4.factorymethod.pizzastore.order;
import com.lesson4.factorymethod.pizzastore.pizza.Pizza;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:42
*/
public abstract class OrderPizza
{
abstract Pizza createPizza(String orderType);
public OrderPizza()
{
Pizza pizza = null;
String orderType;
do
{
orderType = getType();
pizza = createPizza(orderType);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
private String getType()
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String line = reader.readLine();
return line;
} catch (IOException e)
{
e.printStackTrace();
return "";
}
}
}
准备两个继承他的子类
package com.lesson4.factorymethod.pizzastore.order;
import com.lesson4.factorymethod.pizzastore.pizza.BJCheesePizza;
import com.lesson4.factorymethod.pizzastore.pizza.BJHuJiaoPizza;
import com.lesson4.factorymethod.pizzastore.pizza.Pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:38
*/
public class BJOrderPizza extends OrderPizza
{
@Override
Pizza createPizza(String orderType)
{
Pizza pizza = null;
if(orderType.equals("Cheese")){
pizza = new BJCheesePizza();
}else if(orderType.equals("Hujiao")){
pizza = new BJHuJiaoPizza();
}
return pizza;
}
}
package com.lesson4.factorymethod.pizzastore.order;
import com.lesson4.factorymethod.pizzastore.pizza.LDCheesePizza;
import com.lesson4.factorymethod.pizzastore.pizza.LDHujiaoPizza;
import com.lesson4.factorymethod.pizzastore.pizza.Pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:46
*/
public class LDOrderPizza extends OrderPizza
{
@Override
Pizza createPizza(String orderType)
{
Pizza pizza = null;
if(orderType.equals("Cheese")){
pizza = new LDCheesePizza();
}else if(orderType.equals("Hujiao")){
pizza = new LDHujiaoPizza();
}
return pizza;
}
}
客户端
package com.lesson4.factorymethod.pizzastore.order;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:51
*/
public class PizzaStore
{
public static void main(String[] args)
{
new BJOrderPizza();//实例北京OrderPizza
}
}
这时候比如输入Cheese控制台会打印
input pizza 种类:
Cheese
给北京奶酪pizza准备原材料
北京奶酪pizza baking;
北京奶酪pizza cutting;
北京奶酪pizza boxing;
input pizza 种类:
根据我的理解,把pizza制作和卖看做两方,首先做pizza过程定义一个抽象类,由具体的子类去继承,order那边同样负责具体的种类的提供。
抽象工厂模式
-
抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类
-
抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
-
从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一 步的抽象)。
-
将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:36
*/
public abstract class Pizza
{
protected String name;
public void setName(String name)
{
this.name = 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;");
}
}
然后出四种口味pizza
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:23
*/
public class BJCheesePizza extends Pizza
{
@Override
public void prepare()
{
setName("北京奶酪pizza");
System.out.println("给北京奶酪pizza准备原材料");
}
}
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:26
*/
public class BJHuJiaoPizza extends Pizza
{
@Override
public void prepare()
{
setName("北京胡椒pizza");
System.out.println("给北京胡椒pizza准备原材料");
}
}
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:28
*/
public class LDCheesePizza extends Pizza
{
@Override
public void prepare()
{
setName("伦敦奶酪pizza");
System.out.println("给伦敦奶酪pizza准备原材料");
}
}
package com.lesson4.factorymethod.pizzastore.pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 17:27
*/
public class LDHujiaoPizza extends Pizza
{
@Override
public void prepare()
{
setName("伦敦胡椒pizza");
System.out.println("给伦敦胡椒pizza准备原材料");
}
}
其实就是把pizza包下面的五个类放进去
order包下,定义一个接口
package com.lesson4.abstractfactory.pizzastore.order;
import com.lesson4.abstractfactory.pizzastore.pizza.Pizza;
//工厂模式抽象层
public interface ABSFactory
{
Pizza createPizza(String orderType);
}
定义工厂类实现此接口
package com.lesson4.abstractfactory.pizzastore.order;
import com.lesson4.abstractfactory.pizzastore.pizza.BJCheesePizza;
import com.lesson4.abstractfactory.pizzastore.pizza.BJHuJiaoPizza;
import com.lesson4.abstractfactory.pizzastore.pizza.Pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 18:24
*/
public class BJFactory implements ABSFactory
{
@Override
public Pizza createPizza(String orderType)
{
Pizza pizza = null;
if(orderType.equals("Cheese")){
pizza = new BJCheesePizza();
}else if(orderType.equals("Hujiao")){
pizza = new BJHuJiaoPizza();
}
return pizza;
}
}
package com.lesson4.abstractfactory.pizzastore.order;
import com.lesson4.abstractfactory.pizzastore.pizza.LDCheesePizza;
import com.lesson4.abstractfactory.pizzastore.pizza.LDHujiaoPizza;
import com.lesson4.abstractfactory.pizzastore.pizza.Pizza;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 18:24
*/
public class LDFactory implements ABSFactory
{
@Override
public Pizza createPizza(String orderType)
{
Pizza pizza = null;
if(orderType.equals("Cheese")){
pizza = new LDCheesePizza();
}else if(orderType.equals("Hujiao")){
pizza = new LDHujiaoPizza();
}
return pizza;
}
}
package com.lesson4.abstractfactory.pizzastore.order;
import com.lesson4.abstractfactory.pizzastore.pizza.Pizza;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 18:31
*/
public class PizzaOrder
{
ABSFactory factory;
public PizzaOrder(ABSFactory factory){
setFactory(factory);
}
public void setFactory(ABSFactory factory){
this.factory = factory;
Pizza pizza = null;
String orderType="";
do{
orderType = getType();
pizza = factory.createPizza(orderType);
if(pizza !=null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}else {
System.out.println("订购失败!");
break;
}
}while (true);
}
private String getType()
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String line = reader.readLine();
return line;
} catch (IOException e)
{
e.printStackTrace();
return "";
}
}
}
客户端
package com.lesson4.abstractfactory.pizzastore.order;
/**
* @author 朝花不迟暮
* @version 1.0
* @date 2020/8/27 11:51
*/
public class PizzaStore
{
public static void main(String[] args)
{
new PizzaOrder(new BJFactory());
}
}
小结
一、工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统-管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
二、三种工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)
三、设计模式的依赖抽象原则:
➢创建对象实例时,不要直接new类,而是把这个new类的动作放在-个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。
➢不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
➢不要覆盖基类中已经实现的方法。