三个工厂模式(Simple Factory & Factory Method & Abstract Factory)

简单工厂模式(Simple Factory ):

简单工厂又叫做静态工厂方法,其实不是一种设计模式,反而更像是一种编码习惯。


角色及其职责:
工厂(Creator)角色

简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
抽象产品(Product)角色
简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色
是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。


源码:

抽象产品

public interface Car {
    void description();
}
具体产品

public class Benz implements Car{
    public void description() {
        System.out.println("奔驰");
    }
}

public class Bmw implements Car {
    public void description() {
        System.out.println("宝马");
    }
}

工厂:

public class SimpleFactory {
    public static Car produce(String car){
        if (StringUtils.equals("bmw",car)){
            return new Bmw();
        }
        if (StringUtils.equals("benz",car)){
            return new Benz();
        }
        return null;
    }
}

测试方法:

public class Test {
    public static void main(String[] args) {
        Car c1 = SimpleFactory.produce("bmw");
        c1.description();
        Car c2 = SimpleFactory.produce("benz");
        c2.description();
    }
}
运行结果:

宝马
奔驰


优点:
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点:
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
使用场景:
工厂类负责创建的对象比较少;
客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。


工厂方法模式(Factory Method):

与简单工厂模式相比,为了解决工程类中耦合的问题,将原有的实例创建逻辑推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。


角色及其职责

抽象工厂(Creator)角色:
工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色:
这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品(Product)角色
工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品(Concrete Product)角色:
这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。


源码:

抽象工厂:

public interface CarFactory {
    Car produce();
}

具体工厂:

public class BmwFactory implements CarFactory{
    public Car produce() {
        return new Bmw();
    }
}

具体工厂

public class BenzFactory implements CarFactory{
    public Car produce() {
        return new Benz();
    }
}
抽象产品和具体产品与简单工厂模式一样,没有变化。

测试方法:

public class Test {
    public static void main(String[] args) {
        Car c1 = new BenzFactory().produce();
        c1.description();
        Car c2 = new BmwFactory().produce();
        c2.description();
    }
}
运行结果:

奔驰
宝马

这个和简单工厂有区别,简单工厂模式只有一个工厂,工厂方法模式对每一个产品都有相应的工厂。

优点:

增加一个产品,只需要增加新的产品和相对应的工厂,两个类,不需要修改工厂类。

缺点:

增加一个产品,会修改客户端代码,工厂方法只是把简单工厂的内部逻辑判断移到了客户端进行。

使用场景:

对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。


抽象工厂模式(Abstract Factory):

抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品以其使用。

由于抽象工厂模式对应的结果比较复杂,特意找了一个抽象工厂模式的类图,如下:


通过类图可以简单的了解产品树、产品族的概率。然后是抽象工厂模式的角色。

角色及其职责

抽象工厂角色: 

这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:

它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:

它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:

具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。


源码:

抽象工厂:

public interface AbstractFactory {
     Bmw produceBmw();
     Benz produceBenz();
}
具体工厂

public class SedanCarFactory implements AbstractFactory {
    public Bmw produceBmw() {
        return new BmwSedanCar();
    }

    public Benz produceBenz() {
        return new BenzSedanCar();
    }
}

public class SportsCarFactory implements AbstractFactory {
    public Bmw produceBmw() {
        return new BmwSportsCar();
    }

    public Benz produceBenz() {
        return new BenzSportsCar();
    }
}
抽象产品

public abstract class Benz {
    abstract void description();
}
public abstract class Bmw {
    abstract void description();
}

具体产品:

public class BenzSedanCar extends Benz {
    public void description() {
        System.out.println("奔驰小轿车");
    }
}

public class BenzSportsCar extends Benz {
    public void description() {
        System.out.println("奔驰跑车");
    }
}
public class BmwSedanCar extends Bmw {
    public void description() {
        System.out.println("宝马小轿车");
    }
}
public class BmwSportsCar extends Bmw {
    public void description() {
        System.out.println("宝马跑车");
    }
}
测试方法:

public class Test {
    public static void main(String[] args) {
        Bmw bmwSedanCar = new SedanCarFactory().produceBmw();
        bmwSedanCar.description();
        Bmw bmwSportsCar = new SportsCarFactory().produceBmw();
        bmwSportsCar.description();
        Benz benzSportsCar = new SportsCarFactory().produceBenz();
        benzSportsCar.description();
        Benz benzSedanCar = new SedanCarFactory().produceBenz();
        benzSedanCar.description();
    }
}
运行结果:

宝马小轿车
宝马跑车
奔驰跑车
奔驰小轿车


优点:

易于交换产品系列。

缺点:

难以支持新种类的产品(改动的代码很多)。


将抽象工厂模式和工厂方法对比一下:

工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。 
一个抽象工厂类,可以派生出多个具体工厂类。 
每个具体工厂类只能创建一个具体产品类的实例。 
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。 
每个具体工厂类可以创建多个具体产品类的实例。 
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。


使用场景:

一般运用在有产品树、产品族的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值