Java 设计模式之工厂方法模式与抽象工厂模式

栏目: Java · 发布时间: 7年前

内容简介:上一篇《定义:Define an interface for creating an object,but let subclasses decide which class to instantiation.Factory Mehod lets a class defer instantiation to subclasses.翻译过来就是,定义一个用于创建对象的接口,让其子类决定实例化哪个类。工厂方法让一个类的实例化延迟到其子类。上面的定义说明好像很绕口,如果不理解没关系,我们用个例子来说明这个定义:
Java 设计模式之工厂方法模式与抽象工厂模式

一、前期回顾

上一篇《 Java设计模式之单例模式 》详细介绍了单例模式,介绍了单例模式的使用场景,优缺点,同时也写了两种常见的单例模式写法,懒汉式单例模式和饿汉氏单例模式,当然,单例模式的写法还有很多,比如,枚举单例模式,静态内部类单例模式等。有兴趣的可以自行查找资料。本篇开始介绍单例模式的第二篇,工厂方法模式,以及工厂模式的升级版,抽象工厂模式。

二、工厂方法模式的定义与实践

定义:Define an interface for creating an object,but let subclasses decide which class to instantiation.Factory Mehod lets a class defer instantiation to subclasses.翻译过来就是,定义一个用于创建对象的接口,让其子类决定实例化哪个类。工厂方法让一个类的实例化延迟到其子类。

上面的定义说明好像很绕口,如果不理解没关系,我们用个例子来说明这个定义:

//定义产品接口
public interface Iproduct {
    public void doSomething();
}
//产品实现类
public class ProductA implements Iproduct {
    @Override
    public void doSomething() {
        System.out.println("我是产品A,我可以搞事情");
    }
}
//定义工厂类接口
public interface IFactory {
    //创建产品工厂方法
    < T extends Iproduct> T creatProduct(Class<T> clz);
}
//工厂方法实现类
public class ProductFactory implements IFactory {
    @Override
    public <T extends Iproduct> T creatProduct(Class<T> clz) {
        Iproduct product=null;
        try {
            product= clz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}
//场景类
public class Client {
    public static void main(String[] args) {
        IFactory factory=new ProductFactory();
        Iproduct product= factory.creatProduct(ProductA.class);
        product.doSomething();
    }
}
复制代码

上述例子,实现了一个简单的工厂方法模式,定义了一个工厂接口类,然后具体的工厂方法实现了创建对象的逻辑。看到这里,有人肯定会问,这里要new一个工厂类的实例,和我new一个具体的对象有什么区别呢?反正都要自己new,干嘛要搞一个工厂类这么绕呢?对,没错。这里是要new一个工厂类,但是上面的例子创建产品的对象是比较简单,所以感觉不出来,如果ProductA的实例创建是一个非常复杂的过程,那么这个时候我通过工厂方法模式创建对象的实例就很方便了。

肯定还有人问,我觉得上面这个方式还有点啰嗦,有没有更简便的方式实现工厂模式呢?答案是,有。我们接下来看看简单工厂模式。简单工厂方法模式就是上述工厂方法模式的简单版本。我们只要把上述工厂类的接口去掉,然后把工厂实现类改为静态类就可以实现简单工厂方法模式了。代码是这样的:

//这里只去掉了接口,改为静态方法
public class ProductFactory  {
    public static <T extends Iproduct> T creatProduct(Class<T> clz) {
        Iproduct product=null;
        try {
            product= clz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}

public class Client {
    public static void main(String[] args) {
        Iproduct product= ProductFactory.creatProduct(ProductA.class);
        product.doSomething();
    }
}
复制代码

这里就不用自己去new 工厂类啦,代码也简洁了很多。但是去掉了接口也就意味着后面的扩展是不友好的,所以违反了开闭原则。

三、抽象工厂模式的定义与实践

定义:Provide an interface for creating families of related or dependent objects without specifying their concrete classes.翻译: 提供一个创建相关或者相互依赖的对象的接口,并且无需指定他们的具体实现类。

这里理解可能有点困难,为了便于理解,我们先引入两个概念。

产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是汽车,其子类就是各个品牌的汽车,比如奔驰,宝马汽车。汽车和奔驰就构成了一个产品等级结构,抽象汽车是父类,而具体品牌的汽车是其子类。

产品族 :在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如奔驰工厂生产的奔驰跑车,宝马公司生产的跑车,奔驰跑车位于奔驰产品等级结构中,宝马跑车位于宝马产品等级结构中。

所以,汽车和品牌是一个产品等级结构,而每个品牌下面有多个产品线,也就是说奔驰牌下面的汽车有多个产品族,比如跑车族,SUV族。奔驰跑车和宝马跑车是一个产品族,奔驰SUV和宝马SUV是一个产品族。所以上面定义中“相关或者相互依赖的对象”就是场景中包含, 同一个等级结构中有不同的产品族。 ,我们来用一个实际场景来说明下。

假设,我需要一个汽车工厂,汽车可以生产跑车和SUV车型,那么这个时候用之前的工厂方法模式就不满足了,方法工厂模式只能满足生产一个产品,现在需要生产两个产品。所以我们在方法工厂模式的基础上改造下来满足这个场景。

//汽车接口
public interface ICar {
     void dirver();
}
//抽象汽车类
public abstract class AbstractProduct implements ICar{
    @Override
    public void dirver() {
        System.out.println("我是汽车,我可以开动");
    }

    /***
     * 展示不同车的亮点*/
    public abstract void showSpecial();
}
//宝马SUV实现类
public class BmwSuv extends AbstractProduct {
    @Override
    public void showSpecial() {
        System.out.println("我是宝马牌SUV,我的特点就是多功能用途");
    }
}
//宝马跑车实现类
public class BmwProductRoadster extends AbstractProduct {
    @Override
    public void showSpecial() {
        System.out.println("我是宝马跑车,我的特点就是跑的快");
    }
}
//奔驰SUV
public class BenzSuv extends AbstractProduct {
    @Override
    public void showSpecial() {
        System.out.println("我是奔驰牌SUV,我的特点就是多功能用途");
    }
}
//奔驰跑车
public class BenzProductRoadster extends AbstractProduct {
    @Override
    public void showSpecial() {
        System.out.println("我是奔驰跑车,我的特点就是跑的快");
    }
}

//抽象工厂类
public abstract class AbstractFactory {
    //创建跑车
    public abstract < T extends ICar> T createRoadster();
    //创建SUV
    public abstract < T extends ICar> T createSuv();
}
//奔驰汽车工厂类
public class BenzFactory extends AbstractFactory {
    @Override
    public <T extends ICar> T createRoadster() {
        return (T) new BenzProductRoadster();
    }

    @Override
    public <T extends ICar> T createSuv() {
        return (T) new BenzSuv();
    }
}
//宝马汽车工厂类
public class BmwFactory extends AbstractFactory {
    @Override
    public <T extends ICar> T createRoadster() {
        return (T) new BmwProductRoadster();
    }

    @Override
    public <T extends ICar> T createSuv() {
        return (T) new BmwSuv();
    }
}
//场景类
public class Client {
    public static void main(String[] args) {
        AbstractFactory bmwFactory=new BmwFactory();
        AbstractFactory benzFactory=new BenzFactory();
        AbstractProduct bmwRoadster= bmwFactory.createRoadster();
        AbstractProduct bmwSuv=bmwFactory.createSuv();
        AbstractProduct benzRoadster=benzFactory.createRoadster();
        AbstractProduct benzSuv=benzFactory.createSuv();
        bmwRoadster.showSpecial();
        bmwSuv.showSpecial();
        benzRoadster.showSpecial();
        benzSuv.showSpecial();
    }
}

复制代码

细心的读者应该发现,我们的改造相对于工厂方法模式而言,只是抽象工厂模式新增了多一个创建方法。这也是抽象工厂模式和工厂方法模式最明显的区别,抽象工厂模式可以满足多类型,多业务的场景,比如汽车工厂可以生产多种类型汽车,就适用于抽象工厂模式。而普通工厂方法模式就是针对生产某一种对象而言比较适用。总结来说就是,抽象工厂模式适用于多产品族的情况,普通工厂方法模式适用于单产品族情况。

四、总结

上面介绍了工厂方法模式与抽象工厂模式的定义与实践,同时也衍生了一个简单工厂模式。我们先来总结下工厂模式的优点与缺点。

优点:

1.良好的封装性,代码结构清晰,不用关注具体对象的创建过程,符合迪米特法则。

2.良好的扩展性,我们扩展了产品,只要新建对应的工厂类,实现自己的实现逻辑即可。

缺点:

1.对于抽象工厂模式,产品族的扩展比较困难,需要修改顶部抽象工厂类,这会导致所有实现类都要修改,不符合开闭原则。

2.对于简单工厂模式,由于没有接口和抽象父类的约束,从而也会导致扩展只能修改代码,不符合开闭原则。

最后我们列一个表格来总结下工厂方法模式,简单工厂模式,抽象工厂模式的区别。

简单工厂模式 工厂方法模式 抽象工厂模式
有无接口或抽象类
适用场景 一般不涉及扩展,单产品族 涉及单产品族,便于扩展 多产品族场景,可以扩展等级结构,不便于扩展产品族
实现复杂度 最简单 简单 一般

以上所述就是小编给大家介绍的《Java 设计模式之工厂方法模式与抽象工厂模式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Coming of Age in Second Life

Coming of Age in Second Life

Tom Boellstorff / Princeton University Press / 2008-04-21 / USD 29.95

The gap between the virtual and the physical, and its effect on the ideas of personhood and relationships, is the most interesting aspect of Boellstorff's analysis... Boellstorff's portrayal of a virt......一起来看看 《Coming of Age in Second Life》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具