设计模式-简单工厂模式、工厂模式、抽象工厂模式在Java中的使用示例

场景

软件架构设计原则-开闭、依赖倒置、单一职责、接口隔离、迪米特、里氏替换、合成复用,附Java语言示例讲解:

软件架构设计原则-开闭、依赖倒置、单一职责、接口隔离、迪米特、里氏替换、合成复用,附Java语言示例讲解_霸道流氓气质的博客-CSDN博客

在上面讲了软件架构设计原则后,还有常用的设计模式-简单工厂模式、工厂模式、抽象工厂模式的使用示例。

简单工厂模式(Simple Factory Pattern)

是指由一个工厂对象决定创建哪一种产品类的实例,其不属于Gof的23种设计模式。简单工厂适用于工厂类负责创建

的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象不需要关心。

工厂方法模式(Factory Method Pattern)

是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法模式让类的实例化推迟到

子类中进行。在工厂方法模式中用户只关心所需产品对应的工厂,无需关心创建细节,而且加入新的产品时符合开闭原则。

工厂方法模式主要解决产品扩展的问题。

在简单工厂模式中,随着商品的增多,如果每个商品的购买逻辑有区别,则工厂的职责就会变得越来越多,就比如万能工厂。

根据单一职责原则将职能拆分,专厂干专事。比如电脑由电脑工厂创建,书籍由书籍工厂创建,对工厂本身也做一个抽象。

抽象工厂模式(Abstract Factory Pattern)

是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们的具体类。客户端(应用层)不依赖于产品类实例如何被创建、如何

被实现等细节,强调的是一系列相关的产品对象(属于同一个产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类

的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

产品等级结构与产品族

设计模式-简单工厂模式、工厂模式、抽象工厂模式在Java中的使用示例_第1张图片

 

上图中有正方形、圆形和菱形三种图形,相同颜色深浅的代表同一个产品族,相同形状的代表同一个产品等级结构。

类比:

A厂家的多个电器,颜色最深的正方形代表A厂家的洗衣机,颜色最深的圆形代表A厂家的空调,颜色最深的菱形

代表A厂家的热水器,颜色最深的一排都属于A的电器这个产品族。

再看最右侧的菱形,颜色最深的是A厂家,第二排颜色浅点的代表B厂家,同理下面还有C厂家、D厂家、E厂家。

所以同一个厂家的就认为是具体的工厂,每个厂家都生产洗衣机、热水器和空调。

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

简单工厂模式示例

以商品为例,定义一个商品的标准接口

package com.ruoyi.demo.designPattern.simpleFactory;

public interface IGoods {
    /**
     * 购买商品
     */
    public void buy();
}

创建一个电脑商品的实现类

package com.ruoyi.demo.designPattern.simpleFactory;

public class ComputerGoods implements IGoods{
    @Override
    public void buy() {
        System.out.println("购买了电脑商品");
    }
}

客户端调用时会这样写

package com.ruoyi.demo.designPattern.simpleFactory;

public class factoryTest {
    public static void main(String[] args) {
        IGoods goods = new ComputerGoods();
        goods.buy();
    }
}

上述代码中,父类IGoods指向子类ComputerGoods的引用,应用层代码需要依赖ComputerGoods,

如果业务扩展,那么客户端依赖会越来越臃肿。

所以用简单工厂模式对代码进行优化

创建工厂GoodsFactory

package com.ruoyi.demo.designPattern.simpleFactory;

public class GoodsFactory {
    public IGoods buy(Class clazz){
        try {
            if(null != clazz){
                return clazz.newInstance();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

这里采用反射技术,当商品不断增多时,不需要修改工厂中的代码。

此时优化客户端代码

package com.ruoyi.demo.designPattern.simpleFactory;

public class factoryTest {
    public static void main(String[] args) {
        GoodsFactory factory = new GoodsFactory();
        IGoods goods = factory.buy(ComputerGoods.class);
        goods.buy();
    }
}

简单工厂模式也有它的缺点:

工厂类的职责相对过重,不易于扩展过于复杂的产品结构。

工厂方法模式示例

为了实现专厂干专事,电脑商品由电脑工厂创建,书籍商品由书籍工厂创建,对工厂本身做一个抽象。

创建IGoodsFactory

package com.ruoyi.demo.designPattern.factoryMethod;

public interface IGoodsFactory {
    IGoods create();
}

再分别创建子工厂,电脑工厂代码如下

package com.ruoyi.demo.designPattern.factoryMethod;

public class ComputerGoodsFactory implements IGoodsFactory {
    @Override
    public IGoods create() {
        return new ComputerGoods();
    }
}

书籍工厂代码如下

package com.ruoyi.demo.designPattern.factoryMethod;

public class BookGoodsFactory implements IGoodsFactory {
    @Override
    public IGoods create() {
        return new BookGoods();
    }
}

其它的如上面一样,分别是

IGoods:

package com.ruoyi.demo.designPattern.factoryMethod;

public interface IGoods {
    /**
     * 购买商品
     */
    public void buy();
}

ComputerGoods:

package com.ruoyi.demo.designPattern.factoryMethod;


public class ComputerGoods implements IGoods {
    @Override
    public void buy() {
        System.out.println("购买了电脑商品");
    }
}

BoolGoods:

package com.ruoyi.demo.designPattern.factoryMethod;


public class BookGoods implements IGoods {
    @Override
    public void buy() {
        System.out.println("购买了书籍商品");
    }
}

测试代码如下:

package com.ruoyi.demo.designPattern.factoryMethod;

public class factoryMethodTest {
    public static void main(String[] args) {
        IGoodsFactory factory = new ComputerGoodsFactory();
        IGoods goods = factory.create();
        goods.buy();

        factory = new BookGoodsFactory();
        goods = factory.create();
        goods.buy();
    }
}

工厂方法模式适用于以下场景:

1、创建对象需要大量重复的代码。

2、客户端(应用层)不依赖于产品类实例如何被创建、如何被实现等细节。

3、一个类通过其子类来指定创建哪个对象。

工厂方法模式也有缺点:

1、类的个数容易增多,增加复杂度。

2、增加了系统的抽象性和理解难度。

抽象工厂模式示例

通过上面同一个厂家的就认为是具体的工厂,每个厂家都生产洗衣机、热水器和空调。

假如商品要扩展经营模式,除了提供实体商品,还要提供售后服务。

在产品等级中增加两个产品:

IEntityGoods实物商品和IServiceAfterSale售后服务。

IEntityGoods:

package com.ruoyi.demo.designPattern.abstractFactory;

public interface IEntityGoods {
    /**
     * 购买实体商品
     */
    public void buy();
}

IServiceAfterSale:

package com.ruoyi.demo.designPattern.abstractFactory;

/**
 * 售后服务
 */
public interface IServiceAfterSale {
    //享受售后服务
    void enjoy();
}

然后创建一个抽象工厂类GoodsFactory:

package com.ruoyi.demo.designPattern.abstractFactory;

/**
 * 抽象工厂是用户的主入口
 * 是Spring中应用得最广泛的一种设计模式
 * 易于扩展
 */
public interface GoodsFactory {
    IEntityGoods createEntityGoods();
    IServiceAfterSale createServiceAfterSale();
}

然后创建电脑产品组的实体电脑类

package com.ruoyi.demo.designPattern.abstractFactory;

public class ComputerEntityGoods implements IEntityGoods {
    @Override
    public void buy() {
        System.out.println("购买了实体电脑商品");
    }
}

扩展产品等级电脑的售后服务类

package com.ruoyi.demo.designPattern.abstractFactory;

public class ComputerServiceAfterSale implements IServiceAfterSale{
    @Override
    public void enjoy() {
        System.out.println("享受了电脑的售后服务");
    }
}

创建电脑产品族的具体工厂ComputerGoodsFactory

package com.ruoyi.demo.designPattern.abstractFactory;

public class ComputerGoodsFactory  implements GoodsFactory{

    @Override
    public IEntityGoods createEntityGoods() {
        return new ComputerEntityGoods();
    }

    @Override
    public IServiceAfterSale createServiceAfterSale() {
        return new ComputerServiceAfterSale();
    }
}

然后再创建书籍产品的实体书籍类

package com.ruoyi.demo.designPattern.abstractFactory;

public class BookEntityGoods implements IEntityGoods {
    @Override
    public void buy() {
        System.out.println("购买了实体书籍商品");
    }
}

扩展产品等级书籍售后服务类

package com.ruoyi.demo.designPattern.abstractFactory;

public class BookServiceAfterSale implements IServiceAfterSale{
    @Override
    public void enjoy() {
        System.out.println("享受了书籍的售后服务");
    }
}

创建书籍产品族的具体工厂

package com.ruoyi.demo.designPattern.abstractFactory;

public class BookGoodsFactory implements GoodsFactory{
    @Override
    public IEntityGoods createEntityGoods() {
        return new BookEntityGoods();
    }

    @Override
    public IServiceAfterSale createServiceAfterSale() {
        return new BookServiceAfterSale();
    }
}

客户端调用代码

package com.ruoyi.demo.designPattern.abstractFactory;

public class absFacTest {
    public static void main(String[] args) {
        ComputerGoodsFactory computerGoodsFactory = new ComputerGoodsFactory();
        computerGoodsFactory.createEntityGoods().buy();
        computerGoodsFactory.createServiceAfterSale().enjoy();

        BookGoodsFactory bookGoodsFactory = new BookGoodsFactory();
        bookGoodsFactory.createEntityGoods().buy();
        bookGoodsFactory.createServiceAfterSale().enjoy();
    }
}

上面的代码完整地描述了两个产品族:电脑产品族和书籍产品族,也描述了两个产品族等级实体商品

和售后服务。抽象工厂模式完美描述了这样一层复杂的关系。但是,如果我们再扩展产品等级,

比如将运费也加入到商品,那么代码从抽象工厂到具体工厂要全部调整,不符合开闭原则。

所以抽象工厂模式是有缺点的:

1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。

2、增加了系统的抽象性和理解难度。

你可能感兴趣的:(架构之路,java,设计模式,简单工厂模式)