乐Coding程序员

设计模式一(工厂方法模式)

2017-02-18  本文已影响45人  乐Coding

原来大学时期学了两年的Java好久没用全给忘了,最近有时间开始重拾Java。而设计模式没有语言限制,了解后对大家的能力提升和工作效率都有帮助。

Java中共有23中设计模式,分成三类:

  1. 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
  2. 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  3. 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

今天简单介绍下工厂方法模式,说到工厂方法模式必须先了解一下简单工厂模式。简单工厂、工厂方法和抽象工厂被称为工厂三兄弟。工厂方法模式解决了简单工厂的”开闭原则“。

简单工厂

简单工厂,就是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

简单工厂模式中包含的角色及其相应的职责如下:

下面我们以创建打印机为例看看具体实现,我们先定义一个抽象打印机接口:

/**
 * 打印机
 */
public interface Printer {
    void  print();
}

然后定义它的两个实例喷墨打印机和激光打印机

/**
 * 喷墨打印机
 */
class InkJetPrinter implements Printer{
    @Override
    public void print() {
        System.out.println("喷墨打印机doing...");
    }
}
/**
 * 激光打印机
 */
class LaserPrinter implements Printer{
    @Override
    public void print() {
        System.out.println("激光打印机doing...");
    }
}

如果我们想创建打印机的实例,如果平常会直接在需要的地方new一个打印机出来。

//1.0 普通创建形式
InkJetPrinter inkJetPrinter = new InkJetPrinter();
inkJetPrinter.print();
LaserPrinter laserPrinter = new LaserPrinter();
laserPrinter.print();

现在采用简单工厂模式,就需要创建一个工厂用来创建打印机,我们叫这个工厂为SimpleFactory。

enum PrinterType{InkJet, Laser}
public class SimpleFactory {
    public static Printer createPrinter(PrinterType type) {
        switch (type){
            case InkJet :
                return  new InkJetPrinter();
            case Laser:
                return  new LaserPrinter();
            default:
                return  null;
        }
    }
}

当需要创建一个工厂的时候,就需要先创建一个简单工厂,然后传入需要创建的打印机类型create一个打印机出来。使用Printer去接受对象,客户端不知道InkJetPrinter和LaserPrinter的存在,只知道怎么使用就行了。

//2.0 简单工厂模式
Printer inkJetPrinter1 = SimpleFactory.createPrinter(PrinterType.InkJet);
inkJetPrinter1.print();
Printer laserPrinter1 = SimpleFactory.createPrinter(PrinterType.Laser);
laserPrinter1.print();

优点:工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。

缺点:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了,这违背了“开闭原则”。

 当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;

工厂方法模式

工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。

工厂方法模式包含以下角色:

Paste_Image.png

我们接着以刚才的打印机为例,抽象产品打印机和具体产品我们已经有了,下面需要创建一个抽象工厂 :

//抽象工厂
interface PrinterFactory{
    public Printer createPrinter();
}

以及生产具体产品的具体工厂:

//喷墨打印机工厂
class InkJetFactory implements PrinterFactory {
    @Override
    public Printer createPrinter() {
        return new InkJetPrinter();
    }
}
//激光打印机工厂
class LaserFactory implements PrinterFactory {
    @Override
    public Printer createPrinter() {
        return new LaserPrinter();
    }
}

当需要实例化具体打印机的时候先要创建相应的打印机工厂,然后create具体的打印机。

//3.0 工厂方法模式
InkJetFactory inkJetFactory = new InkJetFactory();
Printer inkJetPrinter2 = inkJetFactory.createPrinter();
inkJetPrinter2.print();

LaserFactory laserFactory = new LaserFactory();
Printer laserPrinter2 = laserFactory.createPrinter();
laserPrinter2.print();

工厂方法模式有哪些优势呢?

当然工厂方法模式也有他的劣势:

工厂方法模式和简单工厂模式虽然都是通过工厂来创建对象,他们之间最大的不同是——工厂方法模式在设计上完全完全符合“开闭原则”。

总结

看到这里可能会有童鞋不理解了,我为什么要这么麻烦先创建一个工厂再创建产品对象呢?我直接new一个对象出来不挺好的吗!我一开始也有这样的疑惑,后来思考了一下。

应该是它主要解决框架或者sdk不想暴露给客户端具体的实例的创建过程,对对象的创建进行分装。

还有一种情况是如果一个对象你在多个不同的文件中创建了实例,当需要改成单例模式或者其他实例化方式的时候就需要改动所有实例化的地方,而使用工厂模式只需要改动相应的工厂一个地方,客户端并不需要任何改动。


更多精彩文章请浏览我的博客:http://lvesli.com,本博客发布也会在 lecoding 微信公众号中同步更新,欢迎大家订阅,有什么问题可以在此一起交流。公众号搜索: 乐Coding 或者 ***lecoding ***或者微信扫描下方二维码:

icon.jpg
上一篇下一篇

猜你喜欢

热点阅读