工厂模式:
工厂模式:是java中最常用的设计模式之一。这种类型的设计模式属于创造型模式。它提供了一种创建对象的最佳方案。
优点:
1.创建对象是只需要知道其名称就可以了,不用去管创建对象的逻辑,只需要关心它的接口;
2.扩展能力很好,想要增加一个种类只需要去增加一个工厂就可以了;
缺点:
想要增加一个产品,需要多增加一个工厂和具体类,使得程序的类个数变多。
简单工厂:
举个案例来说,一个车的品牌A,它有电动型车型(电车EA)和油耗型车型(油车SA),那么我们要制造一个车出来,那么我们原本是用多态的形式,该品牌A为一个接口,下面的车型就为它的实现类,下面的就是对应的类和接口
//品牌A
public interface A {
//定义一个方法表示该车的类型
public void show();
}
//电动型车型
public class EA implements A{
@Override
public void show() {
System.out.println("该车为电动型");
}
}
//油耗型车型
public class SA implements A{
@Override
public void show() {
System.out.println("该车为油耗型");
}
}
那么我们平常是在客户端通过多态的形式创建对应的车,如下:
public class Test {
public static void main(String[] args) {
A a = new EA();
a.show();
}
}
而简单工厂则是把这个创建对象这个过程交给工厂来执行,客户端只需要调用工厂去创建对象,这个创建的过程客户端是看不见的,如下:
工厂:
public class EasyFactory {
//需要生产的车
private A car;
public A creatCar(String type){
switch (type){
case "E":
car = new EA();
break;
case "S":
car = new SA();
break;
}
return car;
}
}
客户端:
public static void main(String[] args) {
EasyFactory factory = new EasyFactory();
//传入E表示需要创建电动型车型
A a = factory.creatCar("E");
a.show();
}
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择动态实例化相关的类,这样就可以把创建车的这个过程隐藏起来,客户端不用知道怎么创建的,去除了客户端与具体产品的依赖。
那么对于简单工厂来说呢,它还是存在缺点的,那就是违背了开闭原则,因为他的工厂中用到了select case,那么我们如果有新的车型混合型车型,那么我们就要去修改原来的工厂类,也就违背了开闭原则。
工厂方法模式:
针对简单工厂的违法开闭原则,那么就有一个新的设计模式来解决这个问题:工厂方法模式。
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。接着上面的例子来说,也就是创建一个工厂接口,让其子类工厂类去实例化决定创建哪一个车型。修改如下:
工厂接口:
public interface Factory {
//声明一个创建车的方法
public A creatCar();
}
工厂子类:
//电动型工厂
public class EAFactory implements Factory{
@Override
public A creatCar() {
return new EA();
}
}
//油耗型工厂
public class SAFactory implements Factory{
@Override
public A creatCar() {
return new SA();
}
}
客户端:
public static void main(String[] args) {
//创建电动型车型工厂
Factory factory = new EAFactory();
//创建电动型车
A a = factory.creatCar();
a.show();
}
这样做,也就符合了开闭原则,如果要增加新的车型,只需要去创建对应的车型类、车型工厂类分别去实现品牌A,工厂接口,重写工厂接口方法,即可,可扩展型很好。
但是同样也存在问题,也就是,如果该车品牌下有许多的车型,那么我们就要创建许多的类去实现对应的接口,类的个数也就变多了。
客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。你想要加功能,本来使改变工厂类,而现在是改变客户端。可以通过反射去解决对应的问题。
抽象工厂模式:
继续上面的例子,如果现在又有一个新的品牌B出现,那么按照我们上面的方法,我们就又要写多个接口,个数又增加了,那么对应的抽象工厂模式也就是对应解决这个问题。
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。也即是创建一个工厂接口,声明多个方法用于创建不同品牌,该接口的子类则实现该接口,并且根据该子类用于创建什么车型的工厂,去实现接口对应的方法创建对应车型的车。改写如下:
工厂接口:
//工厂接口
public interface CarFactory {
//创建A品牌
public A creatA();
//创建B品牌
public B creatB();
}
品牌A和品牌B接口:
//A品牌接口
public interface A {
//说明该车型
public void show();
}
//B品牌接口
public interface B {
//说明该车型
public void show();
}
工厂接口子类:
public class EcarFactory implements CarFactory{
//说明是什么工厂
private String type = "电动";
@Override
public A creatA() {
return new EcarA(type);
}
@Override
public B creatB() {
return new EcarB(type);
}
}
public class ScarFactory implements CarFactory{
//说明是什么工厂
private String type = "油耗";
@Override
public A creatA() {
return new ScarA(type);
}
@Override
public B creatB() {
return new ScarB(type);
}
}
对应品牌下的的车型类:
//A品牌电动型
public class EcarA implements A {
private String type ;
public EcarA() {
}
public EcarA(String type) {
this.type = type;
}
@Override
public void show() {
System.out.println("该车为A品牌"+type+"型车");
}
}
//A品牌油耗型
public class ScarA implements A {
private String type ;
public ScarA() {
}
public ScarA(String type) {
this.type = type;
}
@Override
public void show() {
System.out.println("该车为A品牌下的"+type+"型车");
}
}
//B品牌电动型
public class EcarB implements B {
private String type;
public EcarB() {
}
public EcarB(String type) {
this.type = type;
}
@Override
public void show() {
System.out.println("该车为B品牌下的"+type+"型车");
}
}
//B品牌油耗型
public class ScarB implements B {
private String type ;
public ScarB() {
}
public ScarB(String type) {
this.type = type;
}
@Override
public void show() {
System.out.println("该车为B品牌下的"+type+"型车");
}
}
客户端:
public static void main(String[] args) {
//创建电动型车工厂
CarFactory factory = new EcarFactory();
//创建电动型A车
A a = factory.creatA();
a.show();
}
抽象工厂最大的好处便是易于交换产品系列,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不用的产品配置;它让具体的创建实例过程和客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
总结:
简单工厂的灵活性更高,但是违背开闭原则,对于单个产品。
抽象工厂的灵活性不高,符合开闭原则,对于单个产品。
抽象工厂的灵活性较高,但是违背开闭原则,对于多个产品