- 简单工厂模式
简单工厂模式不是23种设计模式之一!它只是日常编程中一种常用的方法或者说是这是一种习惯。
(1)简单工厂模式又称静态工厂模式(因为,它属工厂角色中定义的方法是静态方法),属于类创建模式,根据需求,我们可以根据传入的参数来返回不同子类的实例(其中用到了多态—继承,重写,向上转型)。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
(2)简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,这样就违背了开闭原则(对于扩展是开放的,对于修改是封闭的),而且产品较多时,工厂方法代码逻辑将会非常复杂。
案例代码如下
抽象产品角色:
package com.shuyu.operation;
import lombok.Data;
@Data
public class Operation {
private double numberA=0;
private double numberB=0;
public double getResult(){
double result=0;
return result;
}
}
实例产品角色:
public class OperationAdd extends Operation{
@Override
public double getResult() {
double result=0;
result=getNumberA()+getNumberB();
return result;
}
}
public class OperationSub extends Operation {
@Override
public double getResult() {
double result=0;
result=getNumberA()-getNumberB();
return result;
}
}
public class OperationMul extends Operation{
@Override
public double getResult() {
double result=0;
result=getNumberA()*getNumberB();
return result;
}
}
public class OperationDiv extends Operation {
@Override
public double getResult() {
double result=0;
if (getNumberB()==0){
try {
throw new Exception("除数不能为0");
} catch (Exception e) {
e.printStackTrace();
}
}else {
result=getNumberA()/getNumberB();
}
return result;
}
}
工厂角色:
public class OpreationFactory {
public static Operation createOperate(String operate){
Operation operation=null;
switch (operate){
case "+":
operation=new OperationAdd();
break;
case "-":
operation=new OperationSub();
break;
case "*":
operation=new OperationMul();
break;
case "/":
operation=new OperationDiv();
break;
}
return operation;
}
}
测试类:
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class SimplefactoryApplicationTests {
@Test
public void contextLoads() {
Operation operation= OpreationFactory.createOperate("+");
operation.setNumberA(1);
operation.setNumberB(4);
log.info("执行结果"+operation.getResult());
}
}
输出结果:5.0
- 工厂方法模式
(1)工厂方法模式与简单工厂模式类似,区别在于使用不同的工厂类创建不同的具体产品对象,各个不同功能的实例对象的创建代码,没有耦合在同一个工厂类里,这也是工厂方法模式对简单工厂模式解耦的一个体现。工厂方法模式克服了简单工厂会违背开闭原则的缺点,又保持了封装对象创建过程的优点。
但工厂方法模式的缺点是每增加一个产品类,就需要增加一个对应的工厂类,增加了额外的开发量。
(2)抽象工厂:工厂模式的核心,提供一个创建对象的接口,任何需要创建对象的具体工厂都要实现这个接口。
具体工厂:实现抽象工厂接口的类,受到调用者的调用从而创建对象。
抽象产品:工厂方法模式所创建的对象的超类。也就是所有具体产品的共同父类。
具体产品:实现抽象工厂接口的类。工厂模式中所有创建的对象都是具体产品的实例。
代码实现如下:
抽象产品和具体产品:
import lombok.Data;
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @className:
* @description:基本运算接口
* @date 2018-11-07 13:11
**/
public interface Operation {
public double getResult(double numberA,double numberB);
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @description:加法类
* @date 2018-11-07 13:32
**/
public class OperationAdd implements Operation{
@Override
public double getResult(double numberA,double numberB) {
double result=0;
result=numberA+numberB;
return result;
}
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @description:除法
* @date 2018-11-07 13:42
**/
public class OperationDiv implements Operation {
@Override
public double getResult(double numberA,double numberB) {
double result=0;
if (numberB==0){
try {
throw new Exception("除数不能为0");
} catch (Exception e) {
e.printStackTrace();
}
}else {
result=numberA/numberB;
}
return result;
}
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @description:乘法
* @date 2018-11-07 13:39
**/
public class OperationMul implements Operation{
@Override
public double getResult(double numberA,double numberB) {
double result=0;
result=numberA*numberB;
return result;
}
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @description:减法类
* @date 2018-11-07 13:35
**/
public class OperationSub implements Operation {
@Override
public double getResult(double numberA,double numberB) {
double result=0;
result=numberA-numberB;
return result;
}
}
抽象工厂和具体工厂:
import lombok.Data;
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @className:
* @description:基本运算接口
* @date 2018-11-07 13:11
**/
public interface Operation {
public double getResult(double numberA,double numberB);
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @description:加法类
* @date 2018-11-07 13:32
**/
public class OperationAdd implements Operation{
@Override
public double getResult(double numberA,double numberB) {
double result=0;
result=numberA+numberB;
return result;
}
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @description:除法
* @date 2018-11-07 13:42
**/
public class OperationDiv implements Operation {
@Override
public double getResult(double numberA,double numberB) {
double result=0;
if (numberB==0){
try {
throw new Exception("除数不能为0");
} catch (Exception e) {
e.printStackTrace();
}
}else {
result=numberA/numberB;
}
return result;
}
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @description:乘法
* @date 2018-11-07 13:39
**/
public class OperationMul implements Operation{
@Override
public double getResult(double numberA,double numberB) {
double result=0;
result=numberA*numberB;
return result;
}
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.operation
* @description:减法类
* @date 2018-11-07 13:35
**/
public class OperationSub implements Operation {
@Override
public double getResult(double numberA,double numberB) {
double result=0;
result=numberA-numberB;
return result;
}
}
- 抽象工厂方法
抽象工厂方法中一个工厂可以生产同一产品族的多中具体产品。
举例:
问题:现有电脑产品配件厂商基于windows和apple生产不同类型的CPU和RAM,请试用抽象工厂模式描述该场景。
问题分析:
Windows产品包含WindowsCPU和WindowsRAM,(WindowsCPU和WindowsRAM属于一个产品族)
Apple产品包含AppleCPU和AppleRAM,(AppleCPU和AppleRAM属于一个产品族)
或者说是CPU包含Windows型和Apple型,RAM包含Windows型和Apple型。
下面说的可以结合后面的例子代码自己试一下,
试下增加一个新的LinuxCPU和LinuxRAM以及新增一个GPU产品是不是符合开闭原则。
①符合开闭原则情况
增加产品族:对于增加新的产品族,抽象工厂模式很好地支持了开闭原则,
只需要增加具体产品并对应增加一个新的具体工厂,对已有代码无须做任何修改。
如LinuxCPU和LinuxRAM,这种只需要新增一个工厂就行,属于扩展,不是修改,所以符合开闭原则情况。
②不符合开闭原则情况
增加新的产品等级结构:增加新的产品等级结构:对于增加新的产品等级结构 ,
需要修改所有的工厂角色,包括抽象工厂类,
在所有的工厂类中都需要增加生产新产品的方法,违背了开闭原则。
如新增一个GPU产品,这属于新增一个新的产品等级结构。
如果是工厂模式,则会创建四个工厂类,分别生产四个产品:WindowsCPU,AppleCPU,WindowsRAM,AppleRAM。
如果是抽象工厂模式,则只需要创建两个工厂类,将这四个产品两两组合(即一个工厂生产多种产品):
工厂1:WindowsCPU,WindowsRAM。工厂2:AppleCPU,AppleRAM
工厂1:WindowsCPU,AppleCPU。工厂2:WindowsRAM,AppleRAM
(上面是两种不同的分产品族的方法)
思路:
- 我选择创建两个接口CPU,RAM,分别创建WindowsCPU,WindowsRAM,AppleCPU,AppleRAM四个类来分别实现对应接口。
public interface CPU {
public void CPURun();
}
public interface RAM {
public void RAMRun();
}
public class WindowsCPU implements CPU{
@Override
public void CPURun() {
System.out.println("windows cpu run!");
}
}
public class WindowsRAM implements RAM{
public void RAMRun() {
System.out.println("windows RAM run!");
}
}
public class AppleCPU implements CPU{
@Override
public void CPURun() {
System.out.println("apple CPU run!");
}
}
public class AppleRAM implements RAM{
@Override
public void RAMRun() {
System.out.println("apple RAM run!");
}
}
3.接下来就是创建工厂类了,抽象工厂顾名思义就是抽象工厂类,所以先创建一个抽象接口再来创建两个工厂实现接口。
public interface interfaceFactory {//抽象工厂
public CPU createCPU();
public RAM createRAM();
}
public class WindowsFactory implements interfaceFactory{
@Override
public CPU createCPU() {
return new WindowsCPU();
}
@Override
public RAM createRAM() {
return new WindowsRAM();
}
}
public class AppleFactory implements interfaceFactory{
@Override
public CPU createCPU() {
return new AppleCPU();
}
@Override
public RAM createRAM() {
return new AppleRAM();
}
}
4.到Test类测试一下
public class Test {
public static void main(String[] args) {
// WindowsCPU windowsCPU = new WindowsCPU();
// windowsCPU.CPURun();
// WindowsRAM windowsRAM = new WindowsRAM();
// windowsRAM.RAMRun();
// AppleCPU appleCPU = new AppleCPU();
// appleCPU.CPURun();
// AppleRAM appleRAM = new AppleRAM();
// appleRAM.RAMRun();
WindowsFactory windowsFactory= new WindowsFactory();
CPU windowsCPU = windowsFactory.createCPU();
RAM windowsRAM = windowsFactory.createRAM();
windowsCPU.CPURun();
windowsRAM.RAMRun();
AppleFactory appleFactory = new AppleFactory();
CPU appleCPU = new AppleFactory().createCPU();
RAM appleRAM = new AppleFactory().createRAM();
appleCPU.CPURun();
appleRAM.RAMRun();
}
}
这只是其中一种方式,还可以创建Windows,Apple抽象类,创建CPU工厂和RAM工厂,CPU工厂生产Windows型和Apple型,RAM工厂同理。方式不唯一。
总结:工厂模式乃是一一对应的关系,一个工厂生产一种产品;抽象工厂模式乃是一个工厂生产多种产品。