当Android遇上设计模式之工厂方法(Factory)模式

设计模式六大原则:

  • 单一职责原则:就一个类仅有一个引起它变化的原因,即类承担的职责单一性;

  • 开放封闭原则:类、模块、函数等应该是可以扩展的,但是不可修改。换句话说,就是面对需求的改变要尽可能地保证相对稳定,尽量通过扩展的方式而不是修改原有的代码来实现。

  • 里氏替换原则:所有引用基类(父类)的地方必须透明地使用其子类对象。换句话说,就是尽量把父类设计为抽象类或者接口,在运行时子类实例替换父类实例,在扩展时通过增加一个新的子类实现;

  • 依赖倒置原则:高层模块不应该依赖低层模块,两者都应该依赖于抽象。换句话说,就是模块间的依赖通过抽象发生,实现类之间不发生直接依赖关系,其依赖关系是通过接口或者抽象类产生。

  • 迪米特原则:一个软件实体应当尽可能少地与其他实体发生相互作用。换句话说,就是通过引入一个合理的第三者来降低现有对象之间的耦合度,同时在设计类时尽量降低成员的访问权限。

  • 接口隔离原则:一个类对另一个类的依赖应该建立在最小接口上。换句话说,就是为各个类建立专用的接口,而不要试图建立一个庞大的接口供所有依赖它的类调用,同时接口中的方法尽量少且少用public修饰,以提高内聚和减少对外交互。

1. 简单工厂模式

2.1 定义

 简单工厂模式又被称为静态工厂方法模式,它是创建型设计模式的一种,但不属于23种GoF设计模式之一。学习简单工厂模式有助于理解接下来要学习的工厂方法模式,它的定义为:由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式UML类图如下:
在这里插入图片描述
 UML类图角色说明:

  • Factory:工厂类,它负责创建各类产品对象,依赖于Product;
  • IProduct:抽象产品类,它负责描述所有具体产品类所共有的方法;
  • Product:具体产品类,它是Factory创建的目标,继承于IProduct。

2.2 代码实现

 在Android开发中,偶尔也会用到简单工厂模式来根据不同的情况创建对应的产品对象实现特定的业务,这种模式就是实现比较简单,避免了直接实例化类(即产品类),从而降低了耦合性。接下来,我们就以工厂生产口罩为例来学习简单工厂模式的实现。由于最近一段时间新型冠状病毒的影响,人们出行不得不佩戴口罩,而并不是所有类型的口罩都能够过滤病毒,通常只有医用外科口罩N95型口罩可预防感染,现在我们的工厂就需要大量的生产这两种类型的口罩。具体代码如下:

(1)抽象产品类,IProduct

/** 抽象产品类
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 负责描述所有具体产品类所共有的方法
 * version: 1.0
 */
public abstract class Mask {
    // 产品的抽象方法,由具体的产品实现
    public abstract void efficacy();
}

(2)具体产品类,Product

  • 医用外科口罩
/** 具体产品
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 医用外科口罩
 * version: 1.0
 */
public class SurgicalMask extends Mask{
    @override
    public void efficacy() {
        Log.d("debug", "预防呼吸道感染");
    }
}
  • N95型口罩
/** 具体产品
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : N95型口罩
 * version: 1.0
 */
public class N95Mask extends Mask{
    @override
    public void efficacy() {
        Log.d("debug", "预防呼吸道感染、防雾霾");
    }
}

(3)工厂类,Factory

/** 工厂类
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 创建指定的产品
 * version: 1.0
 */
public class MaskFactory {
    // 创建具体的产品
    public static Mask createMask(String type) {
        Mask mask = null;
        switch(type) {
            case "n95":
                mask = new N95Mask();
                break;
            case "surgical":
                mask = new SurgicalMask();
                break;
        }
        return mask;
    }
}

 工厂类MaskFactory提供了一个静态方法createMask用来生成不同类型的口罩,我们只需要向其传入表示某种口罩的标志,它就会实例化相应的口罩产品对象。客户端调用工厂类方式:

// 创建医用外科口罩产品实例
Mask surgicalMask = MaskFactory.createMask("surgical");
surgicalMask.efficacy();
// 创建N95口罩产品实例
Mask n95Mask = MaskFactory.createMask("n95");
n95Mask.efficacy();

2.3 使用场景

  • 工厂类负责常见的"产品"对象比较少,且工厂类功能稳定,不需要扩展;
  • 客户端只需传入工厂类的参数就能获得对应的产品对象,而无需关心创建对象的具体逻辑。

 前面说到,简单工厂模式实现较为简单,避免了直接实例化类,从而达到了降低耦合性的目的,但是,当遇到需要添加新的产品类型时,比如上例中我们的工厂需要再生产一种活性炭口罩(用于吸附空气中的污染物)时,就不得不修改工厂类MaskFactory,以添加一个case判断,这就违背了开放-封闭原则。此外,如果工厂需要生产的口罩种类非常之多,这就会导致createMask方法非常臃肿。为了最大程度的解耦和使程序更具扩展性,工厂方法模式便闪亮登场。

2. 工厂方法模式

2.1 定义

 工厂方法模式是创建型设计模式的一种,它的定义为:定义一个用于创建对象的接口,让子类决定实例化哪个类。换句话来说,就是工厂方法使一个类的实例化延迟到其子类。工厂方法模式UML类图如下:
在这里插入图片描述
 从上述类图可知,工厂方法模式对比于简单工厂模式,它把工厂类进一步抽象化,这就使得我们可以根据不同的产品由对应的具体工厂类来创建。UML类图中角色说明:

  • IProduct:抽象产品类,同简单工厂模式;

  • Product:具体产品类,实现IProduct,同简单工厂模式;

  • Factory:抽象工厂类,该方法返回一个IProduct类型的对象;

  • ConcreteFactory:具体工厂类,返回Product实例;

2.2 代码实现

 关于工厂方法模式的代码实现,这里仍以制造口罩为例,IProduct和Product类的实现同简单工厂模式,接下来,我们看下Factory和ConcreteFactory两种类的实现。

(1)抽象工厂类,Factory

/** 抽象工厂类
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 提供具体工厂类公共方法
 * version: 1.0
 */
public abstract class Factory {
    public abstract IProduct createProduct();
}

(2)具体工厂类,ConcreteFactory

  • 专门制造医用外科口罩的工厂
/** 制造医用外科口罩工厂
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 
 * version: 1.0
 */
public class SurgicalMaskFactory {
    @Override
    public IProduct createProduct() {
        return new SurgicalMask();
    }
}
  • 专门制造N95型口罩的工厂
/** 制造N95型口罩工厂
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 
 * version: 1.0
 */
public class N95MaskFactory {
    @Override
    public IProduct createProduct() {
        return new N95Mask();
    }
}

 从上面代码可知,我们将每个产品的创建分别交给对应的具体工厂类即可,也就是说,每个具体的工厂类只负责某种类型口罩的生产,这就符合了设计模式中的开放-封闭原则。假如我们需要新增一款活性炭口罩,就只需要新增一个具体的产品类carbonMask和具体工厂类carbonMaskFactory即可,这也符合了设计模式中的单一职责原则。客户端创建产品对象方法:

// 创建医用外科口罩
Factory surgicalFactory = new SurgicalMaskFactory();
SurgicalMask mask = surgicalFactory.createProduct();
// 创建N95口罩
Factory n95Factory = new N95MaskFactory();
N96Mask mask = n95Factory.createProduct();

2.3 使用场景

 工厂方法模式可以说是简单工厂模式的进一步抽象和扩展,它保留了简单工厂模式的封装优点的同时,让扩展变得简单,更加符合设计模式中的开放-封闭原则单一职责原则,是多态性的重要体现。虽然它的优点很明显,但是缺点也是有的,比如每次添加一个新产品,除了要新增新产品类外,还需要新增与之对应的具体工厂类,这就会导致随着产品的个数的增加,相应的类也会增加。另外,就是一个具体工厂类只能创建一种具体的产品,这貌似有点浪费。根据工厂方式模式的优缺点,它的常见应用场景为:

  • 当一个类不知道它所需要的对象的类时,只知道其所对应的工厂即可;

  • 当一个类希望通过其子类来指定创建对象时,以使得程序更具扩展性;

文章的最后,希望国家能够早日攻克新型冠状病毒,受感染的同胞们早日康复,武汉加油!中国加油!

发布了83 篇原创文章 · 获赞 293 · 访问量 30万+

猜你喜欢

转载自blog.csdn.net/AndrExpert/article/details/104124598