参考博客:
简单工厂模式、工厂模式以及抽象工厂模式(具体)
秒懂设计模式之抽象工厂模式(Abstract FactoryPattern)
抽象工厂模式(通俗易懂)
23种设计模式详解(全23种)
工厂:实例化对象的时候不再使用 new Object()形式,通过一个工厂获得对象
类型:创建型
简单工厂模式
可以根据用户的选择条件来实例化相关的类。
可以看做一条上面有很多种不同实例对象的流水线,用户只需要输入一条命令给switch case(多条机械手),其中一条与命令相对应的机械手就会取出对应的实例对象。
操作接口
package 简单工厂模式.opertion;
public interface Operation {
public double getResult(double numberA,double numberB) throws Exception;
}
具体操作类
加减乘除同理,除法可以多加一个判断除数为0
package 简单工厂模式.opertion;
public class Add implements Operation{
@Override
public double getResult(double numberA, double numberB) {
return numberA + numberB;
}
}
工厂类
package 简单工厂模式.factory;
import 简单工厂模式.opertion.*;
public class EasyFactory {
public static Operation createOperation(String name) {
Operation operationObj = null;
switch (name) {
case "+":
operationObj = new Add();
break;
case "-":
operationObj = new Sub();
break;
case "*":
operationObj = new Mul();
break;
case "/":
operationObj = new Div();
break;
default:
}
return operationObj;
}
}
客户端
package 简单工厂模式.client;
import 简单工厂模式.factory.EasyFactory;
import 简单工厂模式.opertion.Operation;
public class Client {
public static void main(String[] args) throws Exception {
Operation add = EasyFactory.createOperation("+");
Operation sub = EasyFactory.createOperation("-");
Operation mul = EasyFactory.createOperation("*");
Operation div = EasyFactory.createOperation("/");
System.out.println(add.getResult(3, 2));
System.out.println(sub.getResult(3, 2));
System.out.println(mul.getResult(3, 2));
System.out.println(div.getResult(3, 2));
}
}
我们无需提供具体的子类类名,只需要提供一个字符串即可得到相应的实例对象。
当子类的类名更换或者增加子类时我们都无需修改客户端代码,只需要在简单工厂类上增加一个分支判断代码即可。
优点:
工厂隐藏了创建对象时进行加工的过程,相比于直接在客户端new对象并进行加工,方便且易于维护。
缺点
当工厂中生产的对象种类很多、每个创建方法需要写很多的代码,会导致这个简单工厂类很庞大臃肿。
每次增加或者删除子类对象的创建方法都需要打开简单工厂类来进行修改,耦合性高,而且也违反了开闭原则。
工厂模式
相较于简单工厂模式,就是用更多的类来取代switch case分支,每一个分支归于一个类
还拿那个流水线做例子的话,就是为每一种产品开辟一条对应的流水线
操作接口和具体操作类
同上面的简单工厂模式中的
工厂接口
package 工厂模式.factory;
import 简单工厂模式.opertion.Operation;
public interface OperationFactory {
public Operation createOperation() ;
}
具体的工厂类
加减乘除同理
package 工厂模式.factory;
import 简单工厂模式.opertion.Add;
import 简单工厂模式.opertion.Operation;
public class AddFactory implements OperationFactory{
@Override
public Operation createOperation() {
return new Add();
}
客户端
package 工厂模式.client;
import 工厂模式.factory.AddFactory;
import 工厂模式.factory.DivFactory;
import 工厂模式.factory.MulFactory;
import 工厂模式.factory.SubFactory;
public class Client {
public static void main(String[] args) throws Exception {
//生成所有的具体工厂实例
AddFactory addFactory = new AddFactory();
SubFactory subFactory = new SubFactory();
MulFactory mulFactory = new MulFactory();
DivFactory divFactory = new DivFactory();
//进行操作
System.out.println(addFactory.createOperation().getResult(3,2));
System.out.println(subFactory.createOperation().getResult(3,2));
System.out.println(mulFactory.createOperation().getResult(3,2));
System.out.println(divFactory.createOperation().getResult(3,2));
}
}
优点
相对于简单工厂模式,进行了解耦,并克服了违背开闭原则的缺点,又保持了封装对象创建过程的优点。
缺点
把简单工厂的内部逻辑判断转移到了客户端代码来进行,因此客户端的代码也增加了不少。
每增加一个产品类,就需要增加一个对应的工厂类,增加了额外的开发量。
抽象工厂模式
相较于前两种模式,该模式不以产品而是以品牌家族建立工厂
品牌接口
package 抽象工厂模式.factory;
import 抽象工厂模式.product.computer.Computer;
import 抽象工厂模式.product.phone.Phone;
public interface ProductFactory {
Phone getPhoneProduct();
Computer getComputerProduct();
}
小米品牌
package 抽象工厂模式.factory;
import 抽象工厂模式.product.computer.Computer;
import 抽象工厂模式.product.computer.XiaoMiComputer;
import 抽象工厂模式.product.phone.Phone;
import 抽象工厂模式.product.phone.XiaoMiPhone;
public class XiaoMiFactory implements ProductFactory{
@Override
public Phone getPhoneProduct() {
return new XiaoMiPhone();
}
@Override
public Computer getComputerProduct() {
return new XiaoMiComputer();
}
}
华为品牌
package 抽象工厂模式.factory;
import 抽象工厂模式.product.computer.Computer;
import 抽象工厂模式.product.computer.HuaWeiComputer;
import 抽象工厂模式.product.phone.HuaWeiPhone;
import 抽象工厂模式.product.phone.Phone;
public class HuaWeiFactory implements ProductFactory{
@Override
public Phone getPhoneProduct() {
return new HuaWeiPhone();
}
@Override
public Computer getComputerProduct() {
return new HuaWeiComputer();
}
}
电脑产品接口
package 抽象工厂模式.product.computer;
public interface Computer{
void playComputerGame();
}
小米电脑
package 抽象工厂模式.product.computer;
public class XiaoMiComputer implements Computer{
@Override
public void playComputerGame() {
System.out.println("玩小米电脑游戏");
}
}
华为电脑
package 抽象工厂模式.product.computer;
public class HuaWeiComputer implements Computer{
@Override
public void playComputerGame() {
System.out.println("玩华为电脑游戏");
}
}
手机接口
package 抽象工厂模式.product.phone;
public interface Phone {
void playPhoneGame();
}
华为手机
package 抽象工厂模式.product.phone;
public class HuaWeiPhone implements Phone{
@Override
public void playPhoneGame() {
System.out.println("玩华为手机游戏");
}
}
小米手机
package 抽象工厂模式.product.phone;
public class XiaoMiPhone implements Phone{
@Override
public void playPhoneGame() {
System.out.println("玩小米手机游戏");
}
}
客户端
package 抽象工厂模式.client;
import 抽象工厂模式.factory.HuaWeiFactory;
import 抽象工厂模式.factory.XiaoMiFactory;
import 抽象工厂模式.product.computer.Computer;
import 抽象工厂模式.product.phone.Phone;
public class Client {
public static void main(String[] args) {
System.out.println("============小米产品============");
//创建小米工厂
XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();
//生产小米手机
Phone xiaoMiPhone = xiaoMiFactory.getPhoneProduct();
xiaoMiPhone.playPhoneGame();
//生产小米电脑
Computer xiaoMiComputer = xiaoMiFactory.getComputerProduct();
xiaoMiComputer.playComputerGame();
System.out.println("============华为产品============");
//创建华为工厂
HuaWeiFactory huaWeiFactory = new HuaWeiFactory();
//生产华为手机
Phone huaWeiPhone = huaWeiFactory.getPhoneProduct();
huaWeiPhone.playPhoneGame();
//生产华为电脑
Computer huaWeiComputer = huaWeiFactory.getComputerProduct();
huaWeiComputer.playComputerGame();
}
}
效果
============小米产品============
玩小米手机游戏
玩小米电脑游戏
============华为产品============
玩华为手机游戏
玩华为电脑上的游戏
Process finished with exit code 0
优点:
一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象(将一个系列的产品统一一起创建)
缺点:
产品族扩展非常困难,要增加一个系列的某一产品,既要修改工厂抽象类里加代码,又修改具体的实现类里面加代码;
增加了系统的抽象性和理解难度
三种工厂模式的使用选择
-
简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
-
工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
-
抽象工厂 :用来生产不同产品族的全部产品。(支持拓展增加产品;支持增加产品族)