[Design Patterns] 设计模式(二) 工厂方法模式
概述
工厂方法模式(Factory Method Pattern),是工厂模式之一,用于管理对象的创建,并将这些行为封装在子类中,从而完成父类代码和子类对象创建代码的解耦。它定义了一个创建对象的接口(抽象工厂类Creator),但由子类(即具体工厂类)决定要实例化的是哪一个,即将类的实例化推迟到了子类中。
使用场景
工厂模式最重要的用途就是解耦,通过抽象的工厂方法将子类的创建和父类进行解耦,因此适用于复杂对象的创建。
组成元素
- 抽象创建者(Creator):抽象的创建者类,定义了一个抽象的工厂方法,以便让子类实现该方法制造产品;
- 抽象产品类:由创建者创建的具体的产品类;
- 具体创建工厂:最终用来创建对象的工厂;
- 具体产品类:最终要创建的对象;
UML类图
示例一
现有一个电脑专卖店负责组装并售卖电脑,当收到一个订单时,会按照组装电脑—>发货—>派送—>签收的流程完成交易,现在就以它为例,看看如何通过工厂方法模式进行实现。
原始方式
电脑实体类如下:
package com.jyq.factory2;
public class Computer {
private String mName;
public Computer(String mName) {
this.mName = mName;
}
public String toString() {
return mName;
}
}
电脑专卖店如下:
package com.jyq.factory2;
public class ComputerShop {
public void sellComputer(String type, boolean isPro){
Computer computer = createComputer(type, isPro);
transport();
delivery();
signed();
}
public void transport() {
System.out.println("运输中...");
}
public void delivery() {
System.out.println("派件中...");
}
public void signed() {
System.out.println("已签收...");
}
/**
* 组装电脑
* @param type 电脑品牌
* @param isPro 是否高配
* @return
*/
public Computer createComputer(String type,boolean isPro) {
Computer computer = null;
if ("lenovo".equals(type)) {
if (isPro) {
computer = new Computer("Lenovo High Configuration:1000G+16G+i7");
} else {
computer = new Computer("Lenovo Low Configuration:500G+8G+i5");
}
} else {
if (isPro) {
computer = new Computer("Dell High Configuration:1000G+16G+i7");
} else {
computer = new Computer("Dell Low Configuration:500G+8G+i5");
}
}
System.out.println("组装成功:"+computer.toString());
return computer;
}
}
这是最原始的方式实现这个功能。然而,随着电脑品牌的不断增多,我们就必须对createComputer()
方法进行不断修改,这显然违背了对修改关闭,对扩展开放的规则,显然是行不通的,于是呢,就出现了下面这种方式。
简单工厂方式
在这个方法中,我们定义一个电脑工厂类,并将组装电脑的任务交给电脑工厂,电脑专卖店只负责从电脑工厂拿货即可,修改下电脑专卖店
package com.jyq.factory2;
public class ComputerShop {
private ComputerFactory cf;
public ComputerShop(ComputerFactory cf) {
this.cf = cf;
}
public void sellComputer(String type, boolean isPro){
Computer computer = cf.createComputer(type, isPro);
transport();
delivery();
signed();
}
public void transport() {
System.out.println("运输中...");
}
public void delivery() {
System.out.println("派件中...");
}
public void signed() {
System.out.println("已签收...");
}
}
创建一个电脑工厂:
package com.jyq.factory2;
public class ComputerFactory {
/**
* @param type 电脑类型
* @param isPro 是否高配
* @return
*/
public Computer createComputer(String type,boolean isPro) {
Computer computer = null;
if ("lenovo".equals(type)) {
if (isPro) {
computer = new LenovoComputer("Lenovo High Configuration:1000G+16G+i7");
} else {
computer = new LenovoComputer("Lenovo Low Configuration:500G+8G+i5");
}
} else {
if (isPro) {
computer = new DellComputer("Dell High Configuration:1000G+16G+i7");
} else {
computer = new DellComputer("Dell Low Configuration:500G+8G+i5");
}
}
return computer;
}
}
这种方式相比于原始方式而言,将实例化工作放在了一个简单的工厂中完成,因此称为简单工厂方式,但是,它并不是一个设计模式,而是一种编程习惯。
随着用户的增加,对电脑品牌的需求也不断加多,因此,电脑商店需要从不同的电脑工厂进货,使用"简单工厂方式"似乎并不能很好的满足要求,这时主角"工厂方法模式"出现。
工厂方法模式
每个电脑品牌都有一个工厂,但他们都基于一个统一的接口,这些就是"抽象创建者"和"具体创建者":
package com.jyq.factory2;
public abstract class ComputerFactory {
public abstract <T extends Computer> T createComputer(Class<T> clz);
}
// 用于生产联想牌电脑工厂
package com.jyq.factory2;
public class LenovoComputerFactory extends ComputerFactory {
@Override
public <T extends Computer> T createComputer(Class<T> clz) {
// TODO Auto-generated method stub
Computer computer = null;
try {
System.out.println("联想工厂开始组装...");
computer = (Computer) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e.toString());
}
return (T) computer;
}
}
//用于生产Dell品牌电脑工厂
package com.jyq.factory2;
public class DellComputerFactory extends ComputerFactory {
@Override
public <T extends Computer> T createComputer(Class<T> clz) {
// TODO Auto-generated method stub
Computer computer = null;
try {
System.out.println("戴尔工厂开始组装...");
computer = (Computer) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (T) computer;
}
}
在这三个工厂中,ComputerFactory定义了一个接口createComputer()
,不同工厂的生产步骤也许有所不同,因此它是被abstract
关键字修饰,所有工厂都可以自己决定如何生产。
这种设计模式就是工厂方法模式,它让子类来决定如何创建对象,以及创建什么对象。
我们补齐剩余代码:
//电脑实体类
package com.jyq.factory2;
public class Computer {
}
package com.jyq.factory2;
public class LenovoComputer extends Computer {
public LenovoComputer() {
System.out.println("喜提联想电脑一台...");
}
}
package com.jyq.factory2;
public class DellComputer extends Computer {
public DellComputer() {
System.out.println("喜提Dell一台...");
}
}
//电脑专卖店
package com.jyq.factory2;
public class ComputerShop {
private ComputerFactory cf;
private Class<? extends Computer> clz;
public ComputerShop(ComputerFactory cf,Class<? extends Computer> clz) {
this.cf = cf;
this.clz = clz;
}
public void sellComputer(){
cf.createComputer(clz);
transport();
delivery();
signed();
}
public void transport() {
System.out.println("运输中...");
}
public void delivery() {
System.out.println("派件中...");
}
public void signed() {
System.out.println("已签收...");
}
}
//客户开始订购电脑
package com.jyq.factory2;
public class DemoFactory {
public static void main(String[] args) {
// TODO Auto-generated method stub
ComputerFactory lcf = new LenovoComputerFactory();
ComputerShop shop = new ComputerShop(lcf,LenovoComputer.class);
shop.sellComputer();
}
}
该例UML类图如下:
示例二
这个示例来自于《Think in java》中第九章,可以更加直观的了解工厂方法模式。该示例工作如下:
创建一个Cycle接口及其Unicycle、Bicycle、Tricycle实现,对每种类型的Cycle创建相应的工厂来生产这些Cycle。
代码如下,首先定义抽象产品类和具体产品类:
/*抽象产品类*/
public interface Cycle {
void go();
}
/*具体产品类*/
public class Unicycle implements Cycle {
@Override
public void go() {
// TODO Auto-generated method stub
System.out.println("Unicycle .....");
}
}
public class Bicycle implements Cycle {
@Override
public void go() {
// TODO Auto-generated method stub
System.out.println("Bicycle .....");
}
}
public class Tricycle implements Cycle {
@Override
public void go() {
// TODO Auto-generated method stub
System.out.println("Tricycle .....");
}
}
再定义抽象工厂类和具体工厂类,并暴露一个工厂方法:
/*抽象工厂类*/
public interface CycleFactory {
Cycle getCycle();
}
/*具体工厂类*/
public class UnicycleFactory implements CycleFactory {
@Override
public Cycle getCycle() {
return new Unicycle();
}
}
public class BicycleFactory implements CycleFactory {
@Override
public Cycle getCycle() {
return new Bicycle();
}
}
public class TricycleFactory implements CycleFactory {
@Override
public Cycle getCycle() {
return new Tricycle();
}
}
最后客户端的调用:
public class CycleTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Cycle c2 = new BicycleFactory().getCycle();
c2.go();
c2 = new UnicycleFactory().getCycle();
c2.go();
c2 = new TricycleFactory().getCycle();
c2.go();
}
}
/**
Bicycle .....
Unicycle .....
Tricycle .....
*/
下一篇: 工厂方法模式——java设计模式(三)