接下来我们来了解一下工厂方法模式,工厂方法模式也是我们开发过程中常常使用到的模式之一,它提供了一种创建对象的最佳方式。在这种模式中,创建对象的具体逻辑被隐藏,我们不需要去考虑具体的创建对象的复杂逻辑。
工厂方法模式可以分为简单工厂模式和普通工厂方法模式。接下来我们以打印机为例来了解一下工厂方法模式。
简单工厂模式
首先我们来了解一下简单工厂模式由哪些部分组成,简单工厂模式主要由3部分组成。
1、抽象产品部分(作为具体产品的父类声明了了具体产品的基本属性和行为,java中使用抽象类或者接口来实现)
2、具体产品部分(具体的产品实例,继承了父类的基本属性和行为,但是各自拥有自己的特别之处)
3、工厂部分(包含了具体产品的创建逻辑,由一个具体的java类来实现)
首先我们来看抽象产品部分的实现:新建一个接口作为所有打印机产品的父类,其中包含一个打印的方法
public interface PrinterInterface {
void print();
}
下面我们来创建我们具体的打印机产品
/**
* 黑白打印机
*/
public class PrinterImlA implements PrinterInterface {
private String printColor = "黑白";
/**
* 一些PrinterImlA特有的属性或者行为
*/
@Override
public void print() {
System.out.println("this is the printColor==" + printColor);
}
}
------------------------------------------------------------------------------
/**
* 彩色打印机
*/
public class PrinterImlB implements PrinterInterface {
private String printColor = "彩色";
/**
* 一些PrinterImlB特有的属性或者行为
*/
@Override
public void print() {
System.out.println("this is the printColor==" + printColor);
}
}
接下来我们看看我们的工厂部分的实现:
public class MyPrinterFactory {
public PrinterInterface getMyPrinter(String switchValue) {
PrinterInterface objValue = null;
if (switchValue.equals("A")) {
objValue = new PrinterImlA();
}
if (switchValue.equals("B")) {
objValue = new PrinterImlB();
}
return objValue;
}
}
最后我们新建一个测试类来测试我们程序
public class MyTest {
public static void main(String[] args) {
MyPrinterFactory factory = new MyPrinterFactory();
PrinterInterface printer1 = factory.getMyPrinter("A");
printer1.print();
PrinterInterface printer2 = factory.getMyPrinter("B");
printer2.print();
}
}
在测试类中我们发现我们并没有关注于具体产品的创建,而是委托给了工厂类,我们只用从中拿过来使用即可。最后我们来看一下控制台输出的信息
D}Z8VBH8EJ2AGYW@DVD$NO4.png
理所当然它们输出了各自相应的信息。但是我们此时再仔细想一想,如果我们此时想加入一个产品(新加一种打印机只打印出白底红字的结果),面对这个要求我们是不是要对工厂类中的getMyPrinter()方法做修改(添加新的判断条件,从而在新的判断条件内做产品创建的操作),很显然这违反了设计原则中的开闭原则(对扩展开放,对修改关闭的原则)。那对于这种情况我们怎么办?好,那我们接下来就看看能不能找到一种方法帮我们解决这个问题。为了让我们的代码符合开闭原则,我们现在修改工厂类中的代码如下
public class MyPrinterFactory {
// public PrinterInterface getMyPrinter(String switchValue) {
// PrinterInterface objValue = null;
// if (switchValue.equals("A")) {
// objValue = new PrinterImlA();
// }
// if (switchValue.equals("B")) {
// objValue = new PrinterImlB();
// }
// return objValue;
// }
/**
* 获取黑白打印机的实例
*/
public PrinterInterface getPrintImlA() {
return new PrinterImlA();
}
/**
* 获取彩色打印机的实例
*/
public PrinterInterface getPrintImlB() {
return new PrinterImlB();
}
}
我们发现我们将每一种打印机产品的创建分离出来了,形成了各自相应的创建方法,当我们需要使用的时候直接调用各自相应的创建方法即可。所以此时我们想要加入一种新的打印机的时候就会很方便,只要我们实现我们事先声明好的接口然后在工厂类中添加一个相应的具体产品的创建方法即可,这就很好的解决了我们遇到的违反开闭原则的问题(前提是在我们不针对于类只针对于函数的情况下)。我们来看看代码实现
/**
* 打印出红色字体的打印机
*/
public class PrinterImlC implements PrinterInterface {
private String printColor = "红色";
/**
* 一些PrinterImlC特有的属性或者行为
*/
@Override
public void print() {
System.out.println("this is the printColor==" + printColor);
}
}
------------------------------------------------------------------------------
public class MyPrinterFactory {
// public PrinterInterface getMyPrinter(String switchValue) {
// PrinterInterface objValue = null;
// if (switchValue.equals("A")) {
// objValue = new PrinterImlA();
// }
// if (switchValue.equals("B")) {
// objValue = new PrinterImlB();
// }
// return objValue;
// }
/**
* 获取黑白打印机的实例
*/
public PrinterInterface getPrintImlA() {
return new PrinterImlA();
}
/**
* 获取彩色打印机的实例
*/
public PrinterInterface getPrintImlB() {
return new PrinterImlB();
}
/**
* 获取红色打印机的实例
*/
public PrinterInterface getPrintImlC() {
return new PrinterImlC();
}
}
------------------------------------------------------------------------------
public class MyTest {
public static void main(String[] args) {
MyPrinterFactory factory = new MyPrinterFactory();
PrinterInterface printer1 = factory.getPrintImlA();
printer1.print();
PrinterInterface printer2 = factory.getPrintImlB();
printer2.print();
PrinterInterface printer3 = factory.getPrintImlC();
printer3.print();
}
}
我们来看看最终的控制台输出结果
![(R[B92W9ILXD4Q)GCU)R.png
到此简单工厂模式就简单介绍完毕!可是我们也注意到了上边的违反开闭原则的解决方案是在针对于函数的情况下,如果我们是针对于这个工厂类来说的话我们还是违反了开闭原则。所以我们究竟该怎么解决这个问题呢?接下来就先了解一下普通工厂方法模式看它能不能帮我们解决这个问题。
普通工厂方法模式
首先我们同样来了解一下普通工厂方法模式由哪些部分组成,
1、抽象产品部分
2、具体产品部分
3、抽象工厂部分
4、具体工厂部分
我们还是以上边的打印机为例,抽象产品部分和具体产品部分的代码就不重复展示了,我们主要来看看抽象工厂和具体工厂部分的代码。
//抽象工厂部分代码:
/**
* 创建打印机的抽象工厂
*/
public interface MyPrinterFactoryInterface {
PrinterInterface createPrinter();
}
//具体工厂部分的代码:
/**
* 创建黑白打印机的具体工厂
*/
public class MyPrinterFactoryA implements MyPrinterFactoryInterface {
@Override
public PrinterInterface createPrinter() {
return new PrinterImlA();
}
}
-------------------------------------------------------------------------------
/**
* 创建彩色打印机的具体工厂
*/
public class MyPrinterFactoryB implements MyPrinterFactoryInterface {
@Override
public PrinterInterface createPrinter() {
return new PrinterImlB();
}
}
//下面我们来看看测试类究竟是怎么调用的:
public class MyTest {
public static void main(String[] args) {
MyPrinterFactoryInterface pIml1 = new MyPrinterFactoryA();
PrinterInterface printer1 = pIml1.createPrinter();
printer1.print();
MyPrinterFactoryInterface pIml2 = new MyPrinterFactoryB();
PrinterInterface printer2 = pIml2.createPrinter();
printer2.print();
}
}
让我们看看最后的控制台输出结果
3ZIE6`R`X5RE}GSBIDL%K%P.png
我们仔细的观察代码之后发现,我们的代码的可扩展性大大的提高了,当我们需要添加一种打印机的时候我们不用再去修改原来的代码了,我们只需要新建具体的产品类和具体的工厂类就可以了,这就完美的解决了简单工厂模式中出现的违反开闭原则的问题。
网友评论