[设计模式] 工厂方法模式

概述

工厂方法模式(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 .....
	*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
工厂方法模式是一种常见的创建型设计模式,它定义了一个用于创建对象的接口,但是由子类决定要实例化的类是哪一个。在工厂方法模式中,创建对象的过程被分离出来,使得这个过程可以被子类定制化,从而提高了代码的可扩展性和可维护性。 工厂方法模式的核心思想是将对象的创建和使用分离开来,客户端只需要知道所需对象的类型,而无需关心对象的创建过程。具体来说,工厂方法模式包含以下几个角色: 1. 抽象工厂(Abstract Factory):定义了工厂方法的接口,用于创建产品对象。 2. 具体工厂(Concrete Factory):实现抽象工厂接口,根据具体需求创建具体产品对象。 3. 抽象产品(Abstract Product):定义了产品的接口,用于描述产品的属性和行为。 4. 具体产品(Concrete Product):实现抽象产品接口,提供具体的实现。 使用工厂方法模式可以将客户端代码和具体产品的实现代码分离开来,使得代码更加灵活和可扩展。工厂方法模式在实际应用中也有很多场景,例如: 1. 当一个类不知道它所必须创建的对象的类的时候。 2. 当一个类希望由它的子类来指定所创建的对象的时候。 3. 当类将创建对象的职责委托给多个帮助子类中的某个特定子类,并且希望能够在运行时切换这些子类中的哪一个时。 总之,工厂方法模式是一种非常实用的设计模式,可以提高代码的可维护性和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值