欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[Design Patterns] 设计模式(二) 工厂方法模式

程序员文章站 2022-06-15 14:09:31
...

概述

工厂方法模式(Factory Method Pattern),是工厂模式之一,用于管理对象的创建,并将这些行为封装在子类中,从而完成父类代码和子类对象创建代码的解耦。它定义了一个创建对象的接口(抽象工厂类Creator),但由子类(即具体工厂类)决定要实例化的是哪一个,即将类的实例化推迟到了子类中。

使用场景

工厂模式最重要的用途就是解耦,通过抽象的工厂方法将子类的创建和父类进行解耦,因此适用于复杂对象的创建。

组成元素

  • 抽象创建者(Creator):抽象的创建者类,定义了一个抽象的工厂方法,以便让子类实现该方法制造产品;
  • 抽象产品类:由创建者创建的具体的产品类;
  • 具体创建工厂:最终用来创建对象的工厂;
  • 具体产品类:最终要创建的对象;

UML类图

[Design Patterns] 设计模式(二) 工厂方法模式

示例一

现有一个电脑专卖店负责组装并售卖电脑,当收到一个订单时,会按照组装电脑—>发货—>派送—>签收的流程完成交易,现在就以它为例,看看如何通过工厂方法模式进行实现。

原始方式

电脑实体类如下:

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类图如下:

[Design Patterns] 设计模式(二) 工厂方法模式

示例二

这个示例来自于《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 .....
	*/
相关标签: 工厂方法模式