工厂设计模式
目的:将客户端的new操作解耦到第三方(工厂类)
假设我有一天想买一个电脑,有surface pro和macbook pro我很喜欢,根据这个场景,可以设计出如下代码:
interface Computer{
void printComputerType();
}
class Surface implements Computer{
@Override
public void printComputerType() {
System.out.println("This is surface Pro");
}
}
class Mac implements Computer{
public void printComputerType(){
System.out.println("This is macbook Pro");
}
}
class Test{
public static void main(String[] args) {
Computer computer = new Surface();
computer.printComputerType();
}
}
假设我突然不想买这两个了,想买一个Alienware,应该怎么办呢?我们需要去客户端修改代码,让客户端支持Alienware笔记本。那么,如何将实例化具体类的代码从客户端中抽离,或者封装起来,使它们不会干扰应用的其他部分呢?这就引入了工厂模式。
一、简单工厂模式——用于产品个数少且且没有家族
简单工厂模式:专门定义一个类用来创建其它类的实例,被创建的实例通常都具有共同的父类。
在上述问题中,这里我们相当于是创建生产电脑的工厂,客户需要购买什么样的电脑,只要输入类型编号就可以获取该电脑。将类的实例化交给工厂,易于解耦。
import java.util.Scanner;
interface Computer{
void printComputerType();
}
class Mac implements Computer{
public void printComputerType(){
System.out.println("this is Mac");
}
}
class Surface implements Computer{
public void printComputerType(){
System.out.println("this is Surface");
}
}
class Factory{
public static Computer fun(String str)
{
Computer c = null;
if(str.equals("mac")){
c = new Mac();
}else if(str.equals("surface")){
c = new Surface();
}
return c;
}
}
class Test{
public static void main(String[] args) {
System.out.println("What do you want?");
java.util.Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
Computer c = Factory.fun(str);
c.printComputerType();
}
}
特点:
1.要有一个抽象产品类(接口)
2.要有多个具体产品类
3.一个工厂(new操作在此工厂中进行)——客户端通过工厂类获取具体实例
优点:易于实现、把类的实例化交给工厂,易于解耦
缺点:添加具体产品需要修改工厂 违反OCP开放封闭原则
二、工厂方法模式(横向扩展方便)——每个产品有自己家族,家族下有很多兄弟
定义一个用来创建对象的接口,让子类决定实例化哪一个类。
针对每个产品(产品族)提供一个工厂类,客户端需要判断使用哪个工厂
interface Computer{
void printComputerType();
}
interface ComputerFactory{
Computer createComputer();
}
class macbookComputer implements Computer{
public void printComputerType(){
System.out.println("This is macbook");
}
}
class surfaceComputer implements Computer{
public void printComputerType(){
System.out.println("This is surface");
}
}
class surfaceFactory implements ComputerFactory{
public Computer createComputer(){
return new surfaceComputer();
}
}
class macbookFactory implements ComputerFactory{
public Computer createComputer(){
return new macbookComputer();
}
}
class Test{
public static void main(String[] args){
ComputerFactory factory = new macbookFactory();
Computer computer = factory.createComputer();
computer.printComputerType();
}
}
对于简单工厂模式而言,创建对象的逻辑判断放在了工厂类中,客户不感知具体的类,但是其违背了开闭原则,如
果要增加新的具体类,就必须修改工厂类。
对于工厂方法模式而言,是通过扩展来新增具体类的,符合开闭原则,但是在客户端就必须要感知到具体的工厂
类,也就是将判断逻辑由简单工厂的工厂类挪到客户端。
工厂方法模式概要
- 一个抽象产品类
- 多个具体产品类
- 一个抽象工厂(针对抽象产品类)
- 多个具体工厂(每个产品家族用于自己的工厂)
优点:
1. 降低了代码耦合度,对象的生成交给子类去完成
2. 实现了开放封闭原则 - 每次添加子产品 不需要修改原有代码
缺点:
1. 增加了代码量,每个具体产品都需要一个具体工厂
2. 当增加抽象产品 也就是添加一个其他产品族 需要修改工厂 违背OCP
简单工厂模式和工厂方法模式总结:
简单工厂模式最大的优点就是工厂内有具体的逻辑去判断生成什么产品,将类的实例化交给了工厂,这样当我
们需要什么产品只需要修改工厂的调用而不需要去修改客户端,对于客户端来说降低了与具体产品的依赖
工厂方法模式是简单工厂的扩展,工厂方法模式把原先简单工厂中的实现那个类的逻辑判断交给了客户端,如
果像添加功能只需要修改客户和添加具体的功能,不用去修改之前的类。
三、抽象工厂模式——多个产品线混合——提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。