设计模式:三大工厂模式

工厂模式:

工厂模式:是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();
    }

抽象工厂最大的好处便是易于交换产品系列,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不用的产品配置;它让具体的创建实例过程和客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。

总结:

简单工厂的灵活性更高,但是违背开闭原则,对于单个产品。

抽象工厂的灵活性不高,符合开闭原则,对于单个产品。

抽象工厂的灵活性较高,但是违背开闭原则,对于多个产品

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值