对象生产基地-工厂模式

概述

工厂模式,顾名思义就是用来产生对象的,一般分为简单工厂模式、工厂方法模式、抽象工厂模式,严格意义上讲简单工厂不算是一种模式,它是简化版的抽象工厂模式,今天我们主要介绍一下工厂方法模式和抽象工厂模式

工厂方式模式

工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。工厂方法模式是常用的创建类型的设计模式,在创建对象是不会向客户端暴露创建逻辑,使用共同的接口来指向新创建的对象

类图

在这里插入图片描述

  • Dress为产品的抽象接口,定义了一个color方法
  • BlackDress、YellowDress、BlueDress为具体的产品
  • AbstractDressFactory为工厂的抽象,定义了创建产品的方法createDress()
  • DressFactory为具体创建产品的工厂

具体实现代码


//抽象产品
public interface Dress {
    public void color();
}

//具体产品BlackDress
public class BlackDress implements Dress {
    @Override
    public void color() {
        System.out.println("Black Dress");
    }
}

//具体产品YellowDress
public class YellowDress implements Dress {
    @Override
    public void color() {
        System.out.println("Yellow Dress");
    }
}

//具体产品BlueDress
public class BlueDress implements Dress {
    @Override
    public void color() {
        System.out.println("Blue Dress");
    }
}

//抽象工厂AbstractDressFactory
public interface AbstractDressFactory {
    public Dress createDress(String name);
}

//具体工厂DressFactory
public class DressFactory implements AbstractDressFactory {

    @Override
    public Dress createDress(String name) {
        if(name == null) return null;
        if("Black".equalsIgnoreCase(name)){
            return new BlackDress();
        } else if("Yellow".equalsIgnoreCase(name)){
            return new YellowDress();
        } else if("Blue".equalsIgnoreCase(name)){
            return new BlueDress();
        }
        return null;
    }
}

public class Client {
    public static void main(String[] args){
        AbstractDressFactory factory = new DressFactory();
        Dress dress = factory.createDress("Blue");
        dress.color();
    }
}

优缺点

优点

  • 良好的封装性,代码结构清晰。调用者想要创建对象,只需要知道名称即可,不需要知道创建的具体细节,降低了模块间的耦合性
  • 良好的扩展性。想增加一个产品,直接扩展一个工厂类就可以
  • 屏蔽产品的具体实现,调用者只用关心产品的接口,实现模块间解耦

缺点

  • 每增加一个产品类,都需要一个具体的产品类和对象实现工厂,类的数量成倍增加,一定程度增加了系统的复杂度

使用场景

  • 一个连接服务,需要支持多种连接协议,比如HTTP、FTP、POP3等,可以将这些协议实现相同的接口
  • 日志记录,日记记录到数据库、本地日志文件、远程服务器上,多种方式可以实现相同的接口

扩展

1.退化为简单工厂模式
假如我们只有一个模块,只需要一个工厂类,那么就不需要把工厂类进行抽象化,增加系统的复杂度,可以直接使用静态方式就可以了

简单工厂模式下的工厂类

public class SimpleDressFactory {
    public static Dress createDress(String name){
        if(name == null) return null;
        if("Black".equalsIgnoreCase(name)){
            return new BlackDress();
        } else if("Yellow".equalsIgnoreCase(name)){
            return new YellowDress();
        } else if("Blue".equalsIgnoreCase(name)){
            return new BlueDress();
        }
        return null;
    }
}

2.扩展为多个工厂类
我们知道,是由具体的工厂类生产具体的产品的,在上面的代码中,所有的产品共用一个工厂类,可以升级为多个工厂类,各自的工厂负责生产各自的产品

public class BlackDressFactory implements AbstractDressFactory {
    @Override
    public Dress createDress(String name) {
        return new BlackDress();
    }
}

public class YellowDressFactory implements AbstractDressFactory {
    @Override
    public Dress createDress(String name) {
        return new YellowDress();
    }
}

public class BlueDressFactory implements AbstractDressFactory {
    @Override
    public Dress createDress(String name) {
        return new BlueDress();
    }
}


此时各自的工厂负责生产各自的产品,name参数已经不需要,可以修改一个工厂,这样做的好处是各司其职,自己负责生产自己的产品,但带来的代价是类的数量成倍的增加,一定程度增加了维护性和系统复杂度。

注意事项

工厂方法模式作为一种创建类型的设计模式,主要用于复杂对象的生成,简单对象的生成直接用new生成就行了,不需要使用工厂模式,如果简单的对象引入工厂方法模式,反而会增加系统的复杂度而得不偿失。任何的设计模式都是为了解决特定的问题,不同的场景我们使用不同的设计模式是为了方便以后的扩展,但我们也不能过度的设计,让原本简单的问题复杂化。

抽象工厂模式

抽象工厂模式,提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体的类。

类图

在这里插入图片描述

  • AbstractShirt、AbstractDress为产品的抽象,他们分别有三个具体的实现
  • AbstractFactory是抽象工厂类,有三个具体的工厂实现
  • 每个具体的工厂都会生产自己的产品簇

具体实现代码


//抽象产品-Dress
public abstract class AbstractDress {
    public abstract void color();
}

public class BlackDress extends AbstractDress {
    @Override
    public void color() {
        System.out.println("Black Dress");
    }
}

public class YellowDress extends AbstractDress {
    @Override
    public void color() {
        System.out.println("Yellow Dress");
    }
}

public class BlueDress extends AbstractDress {
    @Override
    public void color() {
        System.out.println("Blue Dress");
    }
}

public abstract class AbstractShirt {
    public abstract void color();
}

//抽象产品-Shirt
public class BlackShirt extends AbstractShirt {
    @Override
    public void color() {
        System.out.println("Black Shirt");
    }
}

public class YellowShirt extends AbstractShirt {
    @Override
    public void color() {
        System.out.println("Yellow Shirt");
    }
}

public class BlueShirt extends AbstractShirt {
    @Override
    public void color() {
        System.out.println("Blue Shirt");
    }
}

//抽象工厂
public abstract class AbstractFactory {
    public abstract AbstractDress createDress();
    public abstract AbstractShirt createShirt();
}

public class BlackColorFactory extends AbstractFactory {
    @Override
    public AbstractDress createDress() {
        return new BlackDress();
    }

    @Override
    public AbstractShirt createShirt() {
        return new BlackShirt();
    }
}
public class YellowColorFactory extends AbstractFactory {
    @Override
    public AbstractDress createDress() {
        return new YellowDress();
    }

    @Override
    public AbstractShirt createShirt() {
        return new YellowShirt();
    }
}

public class BlueColorFactory extends AbstractFactory {
    @Override
    public AbstractDress createDress() {
        return new BlueDress();
    }

    @Override
    public AbstractShirt createShirt() {
        return new BlackShirt();
    }
}

public class Client {
    public static void main(String[] args){
        AbstractFactory blackFactory = new BlackColorFactory();
        blackFactory.createDress().color();
        blackFactory.createShirt().color();

        AbstractFactory yellowFactory = new YellowColorFactory();
        yellowFactory.createDress().color();
        yellowFactory.createShirt().color();

        AbstractFactory blueFactory = new BlueColorFactory();
        blueFactory.createDress().color();
        blueFactory.createShirt().color();
    }
}

优缺点

优点

  • 封装性,每个产品的实现类不是高层模块要关心的
  • 抽象工厂模式可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理

缺点

抽象工厂模式的最大缺点就是产品族扩展非常困难,假如需要增加一个产品,需要在AbstractFactory中新增加一个create×××()方法,对应的所有具体工厂都要跟着新增这个工厂,这违背了开闭原则

抽象工厂模式使用场景

抽象工厂模式的使用场景非常简单:一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式。
就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点

工厂方法与抽象工厂的比较

  • 所有的工厂都是用来封装对象的,通过减少应用程序和具体的类之间的依赖来减少耦合
  • 工厂方法提供一个抽象接口来创建一个产品,而抽象工厂提供一个抽象接口来创建一个产品家族
  • 工厂方法使用继承来把对象的创建委托给子类,子类实现工厂方法来创建对象。而抽象工厂使用对象组合,对象的创建被实现在工厂接口所暴露出来的方法中
  • 抽象工厂中往往包含有工厂方法模式

总结一下

  • 工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类
  • 工厂方法模式的优点
    • 良好的封装性,代码结构清晰。调用者想要创建对象,只需要知道名称即可,不需要知道创建的具体细节,降低了模块间的耦合性
    • 良好的扩展性。想增加一个产品,直接扩展一个工厂类就可以
    • 屏蔽产品的具体实现,调用者只用关心产品的接口,实现模块间解耦
  • 工厂方法模式的缺点
    • 每增加一个产品类,都需要一个具体的产品类和对象实现工厂,类的数量成倍增加,一定程度增加了系统的复杂度
  • 工厂方法模式的使用场景
    • 一个连接服务,需要支持多种连接协议,比如HTTP、FTP、POP3等,可以将这些协议实现相同的接口
    • 日志记录,日记记录到数据库、本地日志文件、远程服务器上,多种方式可以实现相同的接口
  • 扩展
    • 退化为简单工厂模式
    • 扩展为多个工厂类
  • 注意事项:适度设计,引入设计模式是为了真正的解决问题,避免过度设计增加系统的复杂性
  • 抽象工厂模式,提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体的类
  • 抽象工厂模式的优点
    • 封装性,每个产品的实现类不是高层模块要关心的
    • 抽象工厂模式可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理
  • 抽象工厂模式的缺点
    • 抽象工厂模式的最大缺点就是产品族扩展非常困难
  • 抽象工厂模式使用场景
    • 一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式
  • 工厂方法与抽象工厂的比较
    • 所有的工厂都是用来封装对象的,通过减少应用程序和具体的类之间的依赖来减少耦合
    • 工厂方法提供一个抽象接口来创建一个产品,而抽象工厂提供一个抽象接口来创建一个产品家族
    • 工厂方法使用继承来把对象的创建委托给子类,子类实现工厂方法来创建对象。而抽象工厂使用对象组合,对象的创建被实现在工厂接口所暴露出来的方法中
    • 抽象工厂中往往包含有工厂方法模式

欢迎关注Java天堂公众号,专注于Java相关技术分享

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值