Android设计模式-工厂模式

概述

工厂模式是一种创建者模式,在任何生成复杂对象的地方都可以使用工厂模式。理论来说在任何使用A a = new A()的方式都可以使用工厂模式,虽然使用工厂模式可能需要多做一些工作,但是在后续的开发和维护都带来了方便。

如果我们需要在构建对象的时候,需要做很多的处理工作,比如初始化工作,查询工作等一些耗时的工作,如果我们将这些操作全部放入到构造方法中去写,那么势必在后期维护的带来不方便,而且始化工作如果是很长一段代码,说明要做的工作很多,将很多工作装入一个方法中,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有悖于Java面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间耦合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。

工厂模式分类

  • 简单工厂模式
  • 工厂模式
  • 抽象工厂模式

三者之间的区别:

  1. 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
  2. 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
  3. 简单工厂模式只有一个抽象产品类,一个工厂类。

简单工厂模式

定义:简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法);简单工厂模式可以理解为负责生产对象的一个类,称为“工厂类”。

概括:Concrete Product 具有共同的父类Product。工厂类Factory只有一个,没有子父类,通过向Factory的static方法中传入不同的参数,得到返回的不同的Concrete Product

简单工厂模式uml图

- Factory : 负责生产具体的产品工厂 
- Product: 抽象的产品类, 
- P1: 具体的产品类P1 
- P2: 具体的产品类P2

举个例子。

汽车工厂造汽车的例子。首先Rrtoyewx在大众厂里面上班,一开始被分配到了上海大众里面去了,只管Passat和polo两款车型,而且做的事很简单,就是简单开出去测试一下车子的性能。这个时候事务较少,Rrtoyewx觉得用简单工厂就能搞定了。

- Volkswagen:抽象的大众汽车类 
- Passat,Polo:具体的大众汽车类 
- ShangHaiVolkswagenFactory: 上海大众汽车工厂 
- Client: 客户端类

具体的代码:

产品类 
Volkswagen

public interface Volkswagen {
    void drive();

    String getName();
}

Passat

public class Passat implements Volkswagen {
    public static final int ID = 0;

    @Override
    public void drive() {
        System.out.println("Passat开出去咯,测试成功");  
    }

    @Override
    public String getName() {
        return "Passat";
    }
}

Polo

public class Polo implements Volkswagen{
    public static final int ID = 1;

    @Override
    public void drive() {
        System.out.println("Polo开出去咯,测试成功");
    }

    @Override
    public String getName() {
        return "Polo";
    }
}

工厂类

public class ShangHaiVolkswagenFactory {

    public Volkswagen createVolkswagen(int id){
        Volkswagen volkswagen = null;
        switch(id){
            case Passat.ID:
                volkswagen = new Passat();
                break;
            case Polo.ID:
                volkswagen = new Polo();
                break;
            default:
                volkswagen = null;
        }
        return volkswagen;
    }
}

客户端类

public class Client {
    public static void main(String[] args) {
        ShangHaiVolkswagenFactory factory = new ShangHaiVolkswagenFactory();

        Volkswagen passat = factory.createVolkswagen(Passat.ID);
        passat.drive();

        Volkswagen polo = factory.createVolkswagen(Polo.ID);
        System.out.println(polo.getName());
    }
}

打印出的log为

 

 

每次测试的时候Client类都跑了一遍,似乎很简单,同样的也方便以后的扩展(添加新的车型的时候),只需要添加一个产品类,然后在工厂里添加响应的逻辑就行了。Rrtoyewx觉得自己这个测试车辆程序完全够用了。

注意:对于上面的工厂,可以采用反射的形式去创建产品类,如下面的代码。

public class ShangHaiVolkswagenFactory {

    //产品的id
    public Volkswagen createVolkswagen(int id){
        Volkswagen volkswagen = null;
        switch(id){
            case Passat.ID:
                volkswagen = new Passat();
                break;
            case Polo.ID:
                volkswagen = new Polo();
                break;
            default:
                volkswagen = null;
        }
        return volkswagen;
    }

    //反射得到
    public Volkswagen createVolkswagen(Class <? extends Volkswagen> clazz){
        Volkswagen volkswagen = null;
        try {
            volkswagen = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return volkswagen;
    }
}

优点:

1.将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,实现了解耦;

2.把初始化实例时的工作放到工厂里进行,使代码更容易维护。 更符合面向对象的原则 & 面向接口编程,而不是面向实现编程。

缺点:

1.工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;

2.违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。

3.简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。

工厂模式

定义:工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。

概括:Concrete Product 具有共同的父类Product ,Concrete Factory也具有共同的父类Factory。每个具体的子类Concrete Factory 产出一个对应的Concrete Product。

  • 一个抽象产品,派生出去多种具体的产品的,
  • 一个抽象工厂,派生出多种生产产品的工厂类
  • 一个具体的工厂负责生产一种具体的产品

工厂模式的uml图

- AbstractProduct:抽象的产品类 
- ProductA:具体的A产品 
- ProductB:具体的B产品 
- AbstractFactory:抽象工厂类 
- FactoryA:具体的生产A产品的工厂类 
- FactoryB:具体的生产B产品的工厂类 
- Client: 客户端类

举个栗子

还是上面的栗子的。Rrtoyewx在负责上海大众的两款车型,本来就着简单工厂的模式测试车辆的时候,日子过的非常好,可是好景不长,突然有一天领导说Rrtoyewx说:一汽大众厂最近较忙,看你比较清闲,你就顺便把一汽大众的迈腾,和速腾都测一下。本来Rrtoyewx觉得挺简单的,就是简单再添加一个Magotan和Sagitar,然后通过工厂生成就行了,可是等Rrtoyewx一拿到测试的项目的时候,发现并不是只测试drive,Sagitar和Magotan不仅需要测试drive,而且需要测试brake。好吧,Rrtoyewx觉得以前写的都不能够用了。想了很久,Rrtoyewx 觉得需要将简单工厂模式升级到工厂模式,关注点也发生了改变不再为具体的车辆的,而是一汽大众的车(Magotan和Sagitar)还是上海大众的车(Passat和 Polo)了。

- Volkswagen: 抽象的汽车类 
- ShangHaiVolkswagen:上海大众汽车的抽象类 
- FAWVolkswagen:一汽大众汽车的抽象类 
- Passat,Polo:上海大众厂汽车类的具体类 
- Magotan,Sagitar:一汽大众厂汽车的具体类 
- VolkswagenFactory:抽象的大众汽车工厂 
- ShangHaiVolkswagenFactory:上海大众汽车工厂,主要负责测试Passat和Polo 
- FAWVolkswagenFactory:一汽大众的工厂,主要负责测试Magotan和Sagitar

具体的代码和介绍

抽象类

产品类

Volkswagen类,将Volkswagen类转成抽象类

public abstract class Volkswagen {
    public abstract void drive();

    public abstract String getName();

}

ShangHaiVolkswagen:上海大众汽车的抽象类

public abstract class ShangHaiVolkswagen implements Volkswagen{

}

FAWVolkswagen : 一汽大众汽车的抽象类,多了一个brake()的方法

public abstract class FAWVolkswagen implements Volkswagen {
    public abstract void brake();
}

工厂类

VolkswagenFactory : 汽车工厂的抽象类,并将createVolkswagen(Class clazz)声明称final类型。供子类使用

public abstract class VolkswagenFactory {

    public abstract Volkswagen createVolkswagen(int productID);

    public final Volkswagen createVolkswagen(Class <? extends Volkswagen> clazz){
        Volkswagen volkswagen = null;
        try {
            volkswagen = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return volkswagen;
    };
}

实现类:

产品类

上海大众的具体实现类 
Passat类

public class Passat extends ShangHaiVolkswagen {
    public static final int ID = 0;

    @Override
    public void drive() {
        System.out.println("Passat开出去咯,测试成功");  
    }

    @Override
    public String getName() {
        return "Passat";
    }
}

Polo类

public class Polo extends ShangHaiVolkswagen{
    public static final int ID = 1;

    @Override
    public void drive() {
        System.out.println("Polo开出去咯,测试成功");
    }

    @Override
    public String getName() {
        return "Polo";
    }
}

一汽大众的汽车类。 
Sagitar类,

public class Sagitar extends FAWVolkswagen {
    public static final int ID = 2;

    @Override
    public void drive() {
        System.out.println("Sagitar 开出去了,测试成功了");
    }

    @Override
    public String getName() {
        return "Sagitar";
    }

    @Override
    public void brake(){
        System.out.println("Sagitar 刹车挺好的,测试通过了");
    }
}

Magotan 类

public class Magotan extends FAWVolkswagen{
    public static final int ID = 3;

    @Override
    public void drive() {
        System.out.println("Magotan 开出去咯,测试成功了");
    }

    @Override
    public String getName() {
        return "Magotan";
    }

    @Override
    public void brake(){
        System.out.println("Magotan 刹车挺好的,测试通过");
    }
}

工厂类

注意重载方法的返回类型已经修改称对应的产品类,不在是Volkswagen类型了 
ShangHaiVolkswagenFactory:负责生产上海汽车的工厂类

public class ShangHaiVolkswagenFactory extends VolkswagenFactory {

    public ShangHaiVolkswagen createVolkswagen(int id){
        ShangHaiVolkswagen volkswagen = null;
        switch(id){
            case Passat.ID:
                volkswagen = new Passat();
                break;
            case Polo.ID:
                volkswagen = new Polo();
                break;
            default:
                volkswagen = null;
        }
        return volkswagen;
    }
}

FAWVolkswagenFactory:负责生产一汽汽车的工厂类

public class FAWVolkswagenFactory extends VolkswagenFactory {

    @Override
    public FAWVolkswagen createVolkswagen(int productID) {
        FAWVolkswagen volkswagen = null;
        switch(productID){
            case Magotan.ID:
                volkswagen = new Magotan();
                break;
            case Sagitar.ID:
                volkswagen = new Sagitar();
                break;
            default:
                volkswagen = null;
        }
        return volkswagen;
    }

}

Client类:用来测试

public class Client {
    public static void main(String[] args) {
        System.out.println("开始测试上海大众的车辆");
        ShangHaiVolkswagenFactory factory = new ShangHaiVolkswagenFactory();
        ShangHaiVolkswagen passat = factory.createVolkswagen(Passat.ID);
        passat.drive();

        ShangHaiVolkswagen polo = factory.createVolkswagen(Polo.ID);
        polo.drive();

        System.out.println("开始测试一汽大众的车辆");
        FAWVolkswagenFactory fawFactory = new FAWVolkswagenFactory();

        FAWVolkswagen magotan = fawFactory.createVolkswagen(Magotan.ID);
        magotan.drive();
        magotan.brake();
        FAWVolkswagen sagitar = fawFactory.createVolkswagen(Sagitar.ID);
        sagitar.drive();
        sagitar.brake();
    }
}

打印log的也能够正确的测试:

 

 

 

 

 

 

 

 

通过下面的改变,Rrtoyewx将工厂抽象出生产上海大众的车子和一汽大众的车子的两个工厂,并将一汽大众和上海大众的车子做了区分,形成两个不同产品族的产品系列。并由两个工厂分别对应去生产。等Rrtoyewx做完了这么多后,终于发现原先的系统还是有漏洞的,还是有局限性的,好在及时的弥补。Rrtoyewx发现现有的系统无论处理一汽大众的车子还是上海大众的车子,甚至于再加一个进口大众工厂的车子也够用了。再以后的扩展也能得到了提升了。 

优点:

1、更符合开-闭原则

新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可,而简单工厂模式需要修改工厂类的判断逻辑;

2、符合单一职责原则

每个具体工厂类只负责创建对应的产品,而简单工厂中的工厂类存在复杂的switch逻辑判断;

3、不使用静态工厂方法,可以形成基于继承的等级结构,而简单工厂模式的工厂类使用静态工厂方法

总结:工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现;

缺点:

1、添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;

2、由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

3、虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;

4、一个具体工厂只能创建一种具体产品

抽象工厂类

定义:抽象工厂模式,即Abstract Factory Pattern,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。

概括:

抽象工厂模式引入抽象产品族Abstract Product 的概念,它是所有产品的父类,其下是Product抽象类,它是Abstract Product的子类,是具体产品类的父类,可有多种不同类型,如ProductA 、Product B,再往下,是具体的产品类 Concrete ProductA 、Concrete ProductB;

Concrete Factory 有共同的父类Abstract Factory。每个具体的Concrete Factory都可以生产多种不同产品。如Factory 1 可以生产Concrete ProductA1、Concrete Product B1,Factory 2可以生产Concrete A2、Concrete B2。

  • 多个抽象产品类
  • 每个抽象产品类可以派生出多个具体产品类
  • 一个抽象工厂类,可以派生出多个具体工厂类
  • 每个具体工厂类可以创建多个具体产品类的实例

抽象工厂uml图

- AbstractFactory:抽象工厂类 
- ConcreteFactoryA:具体工厂A,负责生产A和B的 
- ConcreteFactoryB:具体工厂b,负责生产A和B的 
- AbstractProductA,AbstractProductB:抽象的产品类 
- ConcreteProductA1,ConcreteProductA2:具体产品A 
- ConcreteProductB1,ConcreteProductB1:具体产品B 
- Client:客户端

举个栗子

Rrtoyewx在做完上面测试工作之后,上面领导觉得Rrtoyewx工作很不错,想将Rrtoyewx逐渐管理业务层的事(与人打交道),将Rrtoyewx升级了部门经理,同样责任也多了起来了,Rrtoyewx不仅测试原先一些东西,而且需要做一个额外的事情,比如说保险之类。Rrtoyewx在查阅的保险的相关的书籍发现,一汽大众的工厂需要一等保险,而上海大众的车子需要二等保险。 Rrtoyewx 这个时候发现的保险和车子不属于同一个产品。为了处理事务方便Rrotowx需要将原先的系统给升级一下。

新加了几个类 
Insurance:保险的抽象类 
OneLevelInsurance:一等保险的实现类 
TwoLevelInsurance:二等保险的实现类

Insurance类

public abstract class Insurance {
    public abstract String getName();
}

 OneLevelInsurance类

public class OneLevellnsurance extends Insurance{

    @Override
    public String getName() {
        return "一级保险";
    }
}

TwoLevelInsurance类

public class TwoLevelInsurance extends Insurance {

    @Override
    public String getName() {
        return "二级保险";
    }
}

同时修改ShangHaiVolkswagenFactory和FAWVolkswagenFactory以及VolkswagenFactory的代码 
具体如下 
VolkswagenFactory 添加一个生成Insurance类的方法

public abstract class VolkswagenFactory {

    public abstract Volkswagen createVolkswagen(int productID);

    public abstract Insurance bindInsurance();

    public final Volkswagen createVolkswagen(Class <? extends Volkswagen> clazz){
        Volkswagen volkswagen = null;
        try {
            volkswagen = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return volkswagen;
    };
}

ShangHaiVolkswagenFactory绑定一等保险的对象

public class ShangHaiVolkswagenFactory extends VolkswagenFactory {

    public ShangHaiVolkswagen createVolkswagen(int id){
        ShangHaiVolkswagen volkswagen = null;
        switch(id){
            case Passat.ID:
                volkswagen = new Passat();
                break;
            case Polo.ID:
                volkswagen = new Polo();
                break;
            default:
                volkswagen = null;
        }
        return volkswagen;
    }

    @Override
    public Insurance bindInsurance() {  
        return new OneLevellnsurance();
    }
}

FAWVolkswagenFactory类:并定二等保险的对象

public class FAWVolkswagenFactory extends VolkswagenFactory {

    @Override
    public FAWVolkswagen createVolkswagen(int productID) {
        FAWVolkswagen volkswagen = null;
        switch(productID){
            case Magotan.ID:
                volkswagen = new Magotan();
                break;
            case Sagitar.ID:
                volkswagen = new Sagitar();
                break;
            default:
                volkswagen = null;
        }
        return volkswagen;
    }

    @Override
    public Insurance bindInsurance() {
        return new TwoLevelInsurance();
    }
}

Client客户端测试的类

public class Client {
    public static void main(String[] args) {
        System.out.println("开始测试上海大众的车辆");
        ShangHaiVolkswagenFactory factory = new ShangHaiVolkswagenFactory();
        ShangHaiVolkswagen passat = factory.createVolkswagen(Passat.ID);
        passat.drive();

        ShangHaiVolkswagen polo = factory.createVolkswagen(Polo.ID);
        polo.drive();
        Insurance shanghaiInsurance = factory.bindInsurance();
        System.out.println(shanghaiInsurance.getName());

        System.out.println("开始测试一汽大众的车辆");
        FAWVolkswagenFactory fawFactory = new FAWVolkswagenFactory();

        FAWVolkswagen magotan = fawFactory.createVolkswagen(Magotan.ID);
        magotan.drive();
        magotan.brake();
        FAWVolkswagen sagitar = fawFactory.createVolkswagen(Sagitar.ID);
        sagitar.drive();
        sagitar.brake();
        Insurance fawInsurance = fawFactory.bindInsurance();
        System.out.println(fawInsurance.getName());
    }
}

打印log为:

 

 

 

 

 

 

 

Rrtoyewx 做完这些,发现系统已经很健全了,不在为了测试车辆,只要与车辆相关的事宜的对象,由不同的工厂具体去实现。完成这么多,Rrtoyewx 觉得天特别的蓝,心情特别的舒服。

优点:

1、降低耦合

抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展;

2、更符合开-闭原则

新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可,而简单工厂模式需要修改工厂类的判断逻辑;

3、符合单一职责原则

4、每个具体工厂类只负责创建对应的产品,而简单工厂中的工厂类存在复杂的switch逻辑判断;

5、不使用静态工厂方法,可以形成基于继承的等级结构,而简单工厂模式的工厂类使用静态工厂方法;

缺点:

抽象工厂模式很难支持新种类产品的变化。

这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。

总结

  1. 工厂模式是一个创建型的模式
  2. 在任何使用A a = new A()的情况下,理论上说都能使用工厂模式。
  3. 在工厂模式分别的对应使用中,简单工厂模式,注重具体生成的产品,而工厂模式,注重的同一个产品下的不同产品族的产品。如栗子中上海大众的汽车和一汽大众的汽车,抽象工厂模式更多事在与整体产品的架构上,不再是单一一个的抽象产品类。
  4. 工厂模式:一个抽象产品派生出去多个具体的产品,一个抽象工厂派生出多个具体的工厂,而一个具体的工厂对应生成的是一个具体的产品。
  5. 抽象工厂模式:多个抽象产品分别派生出多个具体的产品,一个抽象工厂派生成出多个具体的工厂,一个工厂对应生成多个具体的产品,这些多个抽象产品之间存在着联系
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值