原创

JAVA设计模式(篇三)

温馨提示:
本文最后更新于 2022年10月27日,已超过 918 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

三 工厂方法模式

1.模式的定义与特点

定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。

tips:我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于GoF的23种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”。

优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

缺点:

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

2. 模式的结构与实现

工厂方法模式由抽象工厂具体工厂抽象产品具体产品等4个要素构成。

1. 模式的结构

  • 抽象工厂 :提供创建产品的接口,调用者通过它访问具体工厂创建产品的方法
  • 具体工厂:实现抽象工厂的抽象方法,完成具体产品的创建
  • 抽象产品:定义产品的规范,描述产品的特性和功能
  • 具体产品: 实现抽象产品角色所定义的接口,有具体工厂进行创建,它和具体工厂一一对应

具体结构如图

image-20220727150258128

2. 模式的实现

以鞋子制造工厂为例,用户只需要知道有哪些鞋厂,就能获取到对应鞋厂生产的鞋子

//鞋子抽象工厂
public interface ShoesFactory {

    Shoes makeShoes();

}
//鞋子具体工厂--LiNing
public class LiningFactory implements ShoesFactory {
    @Override
    public Shoes makeShoes() {
        System.out.println("这个品牌是LiNing");
        return new LiningShoes();
    }
}
//鞋子具体工厂--Nike
public class NikeFactory implements ShoesFactory {
    @Override
    public Shoes makeShoes() {
        System.out.println("这个品牌是nike");
        return new NikeShoes();
    }
}
//鞋子抽象产品
public interface Shoes {
    void showMaterial();
}
//鞋子具体产品--LiNing
public class LiningShoes implements Shoes {

    @Override
    public void showMaterial() {
        System.out.println("李宁的材质是纯棉");
    }
}
//鞋子具体产品--Nike
public class NikeShoes implements Shoes {

    @Override
    public void showMaterial() {
        System.out.println("Nike的材质是纯布");
    }
}
//鞋子工厂方法
public class ShoesFactoryUtil{

    //通过类名创建对象
    public static Object getShoesFactory(String className){
        try {
            //通过反射创建对象  com.xxx.为对应类所在的包名
            Class<?> cl = Class.forName("com.xxx."+className);
            Object o = cl.newInstance();
            return o;
        }catch (Exception e){
            return null;
        }
    }
}
//测试
@Test
void testShoes(){
    Shoes shoes;
    ShoesFactory shoesFactory;
    shoesFactory = (ShoesFactory) ShoesFactoryUtil.getShoesFactory("LiningFactory");
    shoes = shoesFactory.makeShoes();
    shoes.showMaterial();
}
//输入LiningFactory
//输出 这个品牌是LiNing  李宁的材质是纯棉

//输入NikeFactory
//输出 这个品牌是nike    Nike的材质是纯布

tips:后续需要加入鸿星尔克等其他品牌时,只需要创建对应的具体工厂具体产品。不会影响其他的品牌

3.应用场景

  • 客户只知道创建产品的工厂名,而不知道具体的产品名。如Nike工厂、LiNing工厂等。
  • 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
  • 客户不关心创建产品的细节,只关心产品的品牌。

4. 模式扩展

当具体产品数量较少,且不会增加或减少,可以直接由一个具体工厂完成,可以删除抽象工厂类。此时的工厂方法模式就变为了简单工厂模式

四 抽象工厂模式

工厂方法模式考虑的是一个工厂只生产一种产品,但是在实际生产和生活中,一个工厂可能会生产多种产品,如LiNing工厂 不仅生产鞋子,还生产衣服,帽子等等

抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,下图为LiNing工厂和Nike工厂对应的关系图

tips: 产品族就是一个具体工厂生产的不同种类的产品。 产品等级就是同一种类型的产品(不同品牌的衣服属于一个产品等级,不同品牌的鞋子属于一个产品等级)

image-20220727170407490

1. 模式的定义与特点

抽象工厂模式的定义∶ 一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。(通过一个具体工厂获取到多个不同等级(类型)的具体产品)

使用抽象工厂模式需要满足的条件

  • 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
  • 系统一次只可能消费其中某—族产品,即同族的产品一起使用。

优点

抽象工厂模式是工厂方法模式的升级版,拥有工厂方法模式的所有优点。其他优点:

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
  • 当增加一个新的产品族时不需要修改原代码,满足开闭原则。

缺点

  • 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

    (新增一个帽子产品时,LiNing工厂和Nike工厂都需要修改)

2.模式的结构与实现

抽象工厂模式同工厂方法模式一样,也是由抽象工厂、具体工厂、抽象产品具体产品等4个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同。

1. 模式的结构

  • 抽象工厂 :提供创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品
  • 具体工厂:实现抽象工厂的抽象方法,完成具体产品的创建
  • 抽象产品:定义产品的规范,描述产品的特性和功能。抽象工厂中有多个抽象产品
  • 具体产品: 实现抽象产品角色所定义的接口,有具体工厂进行创建,它和具体工厂为多对一的关系

结构图

image-20220727171655692

2. 模式的实现

改造工厂方法模式的代码

//鞋子抽象工厂
public interface ShoesFactory {

    Shoes makeShoes();
    Clothes makeClothes();
}
//鞋子具体工厂--LiNing
public class LiningFactory implements ShoesFactory {
    @Override
    public Shoes makeShoes() {
        System.out.println("这个品牌是LiNing");
        return new LiningShoes();
    }

    @Override
    public Clothes makeClothes() {
        System.out.println("生产了LiNing衣服");
        return new LiNingClothes();
    }
}
//鞋子具体工厂--Nike
public class NikeFactory implements ShoesFactory {
    @Override
    public Shoes makeShoes() {
        System.out.println("这个品牌是nike");
        return new NikeShoes();
    }

    @Override
    public Clothes makeClothes() {
        System.out.println("生产了Nike衣服");
        return new NikeClothes();
    }
}
//衣服抽象产品
public interface Clothes {
    void showClothes();
}
//衣服具体产品-nike
public class NikeClothes implements Clothes {

    @Override
    public void showClothes() {
        System.out.println("Nike衣服");
    }
}
//衣服具体产品-LiNing
public class LiNingClothes implements Clothes {

    @Override
    public void showClothes() {
        System.out.println("LiNing衣服");
    }
}

3.模式的应用场景

抽象工厂模式最早的应用是用于创建属于不同操作系统的视窗构件。如 java的AWT 中的Button和Text 等构件在 Windows和 UNIX中的本地实现是不同的。

抽象工厂模式通常适用于以下场景:

  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如服装制造工厂中的鞋子 衣服 袜子等
  • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

4.模式的扩展

抽象工厂模式的扩展有一定的“开闭原则”倾斜性:

  1. 当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。
  2. 当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。

另一方面,当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。

正文到此结束