工厂模式

生么是工厂?

任何一个可以产生对象的类,都可以叫做工厂。但是工厂也分小工厂和大工厂,我们写的普通的类,去new 一个对象,那就是一个小工厂。
举一个简单的例子。

简单工厂

class Car{
    void go(){
        System.out.println("车开始跑了。。。。");
    }
}

 public static void main(String[] args) {
        Car car = new Car();
        car.go();
    }

这里我们定义了一个车类,此时我是一个司机,我需要一辆车,那么就要生产一个汽车给我开,此时Car就给我生产出来了。然后我开着车跑了。

好了那么另一个问题来了,我虽然是个司机,但是不开车,我开飞机,开坦克怎么办?

那我是不是得再写飞机类和坦克类。
此时我们还得让飞机和坦克执行他们运动的方法。现在我们就可以把运动这个方法给抽象为接口,让交通工具去实现不就行了么?这样子类就会设计的高端一点了。

interface Moveable {
    void go();
}
class Car implements Moveable {
    @Override
    public void go() {
        System.out.println("车开始跑了。。。。");
    }
}

class Tank implements Moveable {
    @Override
    public void go(){
        System.out.println("坦克开始跑了。。。。。");
    }
}
class Plane implements  Moveable{
    @Override
    public void go() {
        System.out.println("飞机开始飞了");
    }
}

public static void main(String args[]){
		//我现在是开坦克的,给我造个坦克让我开。
  		Tank tank = new Tank();
        tank.go();
		//我现在又是开飞机的了,给我造个飞机让我开
		Plane plane = new Plane();
        plane.go();
}

大家想一下,这个司机会开那么多载具,但是要买飞机得各奔东西,去完车店,去坦克店,去完坦克店去飞机店。累死了。现在是现代化社会了,就不能一站式服务么?来个工厂,又给我造汽车,又给我造坦克,还给我造飞机!

简单工厂应运而生。
此时我们创建一个工厂

//载具工厂
class VehicleFactory {
    Car createCar(){
        //什么样的人能生产car,什么样的人能拿car,这种权限问题以及各种过程的处理
        return new Car();
    }

    Plane cratePlane(){
        //权限以及逻辑处理。。。。。
        return new Plane();
    }

    Tank createTank(){
        //权限处理。
        return new Tank();
    }
}
public static void main(String args[]){
//载具工厂给我生产 车,飞机坦克让我开。
  VehicleFactory  factory = new VehicleFactory();
        Car car = factory.createCar();
        car.go();
        Plane plane = factory.cratePlane();
        plane.go();
        Tank tank = factory.createTank();
        tank.go();
        //此时还是造个车
        Moveable m = factory.createCar();
        m.go;
}

这样是不是就方便许多了,但是还是会有写问题,我现在也会开船,但是这个厂它不造船啊,这怎么办,现在工厂是不是还得扩展个业务线,再给我造个船。是不是又得添加代码进去,又得写死。假如我现在又要辆劳斯莱斯幻影,这个车和普通的车绝对不同吧。所以是不是还得添加代码进去。
所以我们能很明显的看出来,简单工厂的扩展性并不好
但是我们发现此时我们可以任意的定制一个交通工具了

当然我们也可以对每一个产品,对应一个工厂,这样子可以解决不同车,不同飞机,不同船的问题,并且还解决了交通工具的这个维度上进行了扩展。我想要个船,创建一个船工厂。想要个摩托车,创建一个摩托车工厂。
此时我们就可以任意定制生产的一个过程了。
示例:

//车工厂
class CarFactor{
    Moveable create(){
    //定制任意的一个生产过程
        return new Car();
    }
}
//充分利用下多态
public static void main(String[] args) {
    CarFactor carFactor = new CarFactor();
      Moveable m = carFactor.create();
      m.go();
}

抽象工厂

那我现在要任意定义生产一族呢?
我们先明白产品一族的概念,大家想一下,现实世界的人,和魔法世界的人肯定不一样吧。现实世界的人开车,吃面包,武器是AK47;魔法世界的人,骑扫帚,喝魔法药水,武器是魔法棒

我们现在做一层抽象,车和扫帚是载具,面包和魔法药水是食物,AK47 和 魔法棒是武器。

(注意这是一个是一个的关系,不是有一个的关系,这与前面所定义的car实现moveable不同,车是可以移动,这是车的一个功能,所以定义为接口)

此时这个抽象工厂实际上就是要生产一个对一个族系的人对吧,对应族系的人就有着他们各自不同的特点。
这个抽象工厂就生产族系的人。具体的实现就看自己怎么去具体实现抽象工厂了。

在这里插入图片描述

//载具
abstract class Vehicle{
    abstract void go();
}
//食物
abstract class Food{
    abstract void eat();
}
//武器
abstract class Weapon{
    abstract void  shoot();
}


//抽象工厂
abstract class AbstractFactory{
    //生产载具   
    abstract Vehicle createVehicle();
       
    //生产食物
    abstract  Food createFood();
    
    //生产武器
    abstract Weapon createWeapon();
}

好了对于现代人的实现,我们就得具体实现一个抽象工厂

class Car extends Vehicle {
    @Override
    void go() {
        System.out.println("车开始跑了...");
    }
}

class Bread extends Food{

    @Override
    void eat() {
        System.out.println("吃面包...");
    }
}

class AK47 extends Weapon{

    @Override
    void shoot() {
        System.out.println("AK47tutututtu...");
    }
}

class modernFactory extends AbstractFactory{
    @Override
    Vehicle createVehicle() {
        //巴拉巴拉的权限和过程.
        return new Car();
    }
    @Override
    Food createFood() {
        //巴拉巴拉...
        return new Bread();
    }
    @Override
    Weapon createWeapon() {
        //巴拉巴拉...
        return new AK47();
    }
}

这就是一个具体工厂的实现类了,此时实现的是现代社会。
至于魔法世界,那么就直接再实现一个魔法世界的工厂就好了。
后面我们再加个什么克鲁苏,加个什么龙族社会,实现抽象工厂就好了啊。一换全换。这就跟换皮肤一样的


现在我们来具体说一下抽象工厂的具体概念。

抽象工厂模式(Abstract Factory Pattern)是一种比较常用的模式,‘其定义如下: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们 的具体类。)
在这里插入图片描述

抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象 工厂模式产生需要的对象是一种非常好的解决方式。我们来看看抽象工厂的通用源代码,首 先有两个互相影响的产品线(也叫做产品族),例如制造汽车的左侧门和右侧门,这两个应 该是数量相等的——两个对象之间的约束,每个型号的车门都是不一样的,这是产品等级结 构约束的,我们先看看两个产品族的类图,如图9-4所示。

在这里插入图片描述
有N个产品族,在抽象工厂类中就应该有N个创建方法.

抽象工厂模式的优点

●封装性,每个产品的实现类不是高层模块要关心的,它要关心的是什么?是接口,是 抽象,它不关心对象是如何创建出来,这由谁负责呢?工厂类,只要知道工厂类是谁,我就 能创建出一个需要的对象,省时省力,优秀设计就应该如此。

● 产品族内的约束为非公开状态。例如生产男女比例的问题上,猜想女娲娘娘肯定有自 己的打算,不能让女盛男衰,否则女性的优点不就体现不出来了吗?那在抽象工厂模式,就 应该有这样的一个约束:每生产1个女性,就同时生产出1.2个男性,这样的生产过程对调用 工厂类的高层模块来说是透明的,它不需要知道这个约束,我就是要一个黄色女性产品就可 以了,具体的产品族内的约束是在工厂内实现的

抽象工厂模式的缺点

抽象工厂模式的最大缺点就是产品族扩展非常困难,为什么这么说呢?我们以通用代码 为例,如果要增加一个产品C,也就是说产品家族由原来的2个增加到3个,看看我们的程序 有多大改动吧!抽象类AbstractCreator要增加一个方法createProductC(),然后两个实现类都要 修改,想想看,这严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约。改变 契约,所有与契约有关系的代码都要修改,那么这段代码叫什么?叫“有毒代码”,——只要 与这段代码有关系,就可能产生侵害的危险。

抽象工厂模式的使用场景

抽象工厂模式的使用场景定义非常简单:一个对象族(或是一组没有任何关系的对象) 都有相同的约束,则可以使用抽象工厂模式。什么意思呢?例如一个文本编辑器和一个图片
处理器,都是软件实体,但是*nix下的文本编辑器和Windows下的文本编辑器虽然功能和界 面都相同,但是代码实现是不同的,图片处理器也有类似情况。也就是具有了共同的约束条 件:操作系统类型。于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片 处理器

抽象工厂的注意事项

在抽象工厂模式的缺点中,我们提到抽象工厂模式的产品族扩展比较困难,但是一定要 清楚,是产品族扩展困难,而不是产品等级。在该模式下,产品等级是非常容易扩展的,增 加一个产品等级,只要增加一个工厂类负责新增加出来的产品生产任务即可。也就是说横向 扩展容易,纵向扩展困难。以人类为例子,产品等级中只有男、女两个性别,现实世界还有 一种性别:双性人,既是男人也是女人(俗语就是阴阳人),那我们要扩展这个产品等级也 是非常容易的,增加三个产品类,分别对应不同的肤色,然后再创建一个工厂类,专门负责 不同肤色人的双性人的创建任务,完全通过扩展来实现需求的变更,从这一点上看,抽象工 厂模式是符合开闭原则的。

最佳实践

一个模式在什么情况下才能够使用,是很多读者比较困惑的地方。抽象工厂模式是一个 简单的模式,使用的场景非常多,大家在软件产品开发过程中,涉及不同操作系统的时候, 都可以考虑使用抽象工厂模式,例如一个应用,需要在三个不同平台(Windows、Linux、 Android(Google发布的智能终端操作系统))上运行,你会怎么设计?分别设计三套不同 的应用?非也,通过抽象工厂模式屏蔽掉操作系统对应用的影响。三个不同操作系统上的软 件功能、应用逻辑、UI都应该是非常类似的,唯一不同的是调用不同的工厂方法,由不同的 产品类去处理与操作系统交互的信息。

部分内容摘自《设计模式之禅》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值