顾名思义:工厂就是用来生产的物品;Java中就是用来生产对象的。
Ⅰ、简单工厂
用法:
在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。
描述:
简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。客户类往往有多个,如果不使用简单工厂,那么所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。
产品接口
/**
* 生产样品
* @author zhongguangneng 799762497@qq.com
* @Description
*/
public interface Product {
}
产品类型
/**
* 磁盘
* @author zhongguangneng 799762497@qq.com
* @Description
*/
public class Disk implements Product {
}
/**
* 鼠标
* @author zhongguangneng 799762497@qq.com
* @Description
*/
class Mouse implements Product {
}
/**
* cpu
* @author zhongguangneng 799762497@qq.com
* @Description
*/
class Cpu implements Product {
}
生产线
/**
* 生产线
* @author zhongguangneng 799762497@qq.com
* @Description
*/
public class SimpleFactory {
public Product createProduce(int i){
if(i == 1){
return new Disk();
}else if(i == 2){
return new Cpu();
}else{
return new Mouse();
}
}
/**
* 生产的产品无需知道怎么生产,只需知道需要生产什么产品
* @Description
* @param args
*/
public static void main(String[] args) {
SimpleFactory fa = new SimpleFactory();
Product thing = fa.createProduce(3);
}
}
对于简单工厂来说,
好处在于客户不需要知道产品是如何生产的,只需要告诉工厂我需要什么产品就行,符合开闭原则;
不好在于随着业务的扩张,生产的东西越来越多,工厂的生产线类不太理想,因为每增加一种新产品,都要在生产线类中增加相应的商业逻辑和判 断逻辑,这显自然是违背开闭原则的(相当于生产线需要改造才能生产出新产品)。
简单工厂模式适用于业务简单的情况下或者具体产品很少增加的情况;不利于产品扩展。
如何解决这种问题就要往下看工厂方法模式
Ⅱ、工厂方法模式
知道了简单工厂模式的弊端后,我们需要改造生产线;建立多个生产线,让每个生产线各种负责生产各种的产品;这样的话,我们新开发一种产品就直接new一个产品类和工厂线即可,其他无需改动。客户需要什么产品,我们就告知哪条生产线生产;
实现方法:创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。
/**
* 生产线抽象类
* @author zhongguangneng 799762497@qq.com
* @Description
*/
public abstract class Factory {
abstract public Product factoryMethod();
public Product doSomething() {
Product product = factoryMethod();
return product;
// do something with the product
}
}
/**
* 多个生产线
* @author zhongguangneng 799762497@qq.com
* @Description
*/
public class DiskFactory extends Factory {
@Override
public Product factoryMethod() {
// TODO Auto-generated method stub
return new Disk();
}
}
class CpuFactory extends Factory {
@Override
public Product factoryMethod() {
// TODO Auto-generated method stub
return new Cpu();
}
}
class MouseFactory extends Factory {
@Override
public Product factoryMethod() {
// TODO Auto-generated method stub
return new Mouse();
}
}
public class FactoryMethod {
public static void main(String[] args) {
// TODO Auto-generated method stub
//生产磁盘
Product d = new DiskFactory().doSomething();
//生产cpu
Product c = new CpuFactory().doSomething();
//....
}
}
Ⅳ、 抽象工厂(Abstract Factory)
重点:提供一个接口,用于创建 相关的对象家族 。
例子:生产电脑的配件有多种多样,适合配件多样化的。
说明:抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory 中的 createDisk() 和 createCpu() 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂方法模式的定义
缺点:新增加产品类困难,修改麻烦。
/**
* 磁盘抽象类
* @author zhongguangneng 799762497@qq.com
* @Description
*/
public abstract class AbstractDisk implements Product{
}
/**
* 磁盘A类型
* @author zhongguangneng 799762497@qq.com
* @Description
*/
class DiskA extends AbstractDisk{
}
/**
* 磁盘B类型
* @author zhongguangneng 799762497@qq.com
* @Description
*/
class DiskB extends AbstractDisk{
}
/**
* Cpu
* @author zhongguangneng 799762497@qq.com
* @Description
*/
abstract class AbstractCpu implements Product{
}
class CpuA extends AbstractCpu{
}
class CpuB extends AbstractCpu{
}
/**
* 抽象工厂方法
* @author zhongguangneng 799762497@qq.com
* @Description
*/
public abstract class AbstractFactory {
abstract AbstractDisk createDisk(String name);
abstract AbstractCpu createCpu(String name);
}
public class Factory extends AbstractFactory{
@Override
AbstractDisk createDisk(String name) {
// TODO Auto-generated method stub
if(name == null){
return null;
}
if("diskA".equals(name)){
return new DiskA();
}
if("diskB".equals(name)){
return new DiskB();
}
return null;
}
@Override
AbstractCpu createCpu(String name) {
// TODO Auto-generated method stub
if(name == null){
return null;
}
if("cpuA".equals(name)){
return new CpuA();
}
if("cpuB".equals(name)){
return new CpuB();
}
return null;
}
}
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
AbstractFactory f = new Factory();
AbstractCpu cpu = f.createCpu("cpuA");
AbstractDisk disk = f.createDisk("diskA");
}
}