手记

设计模式(二)-创建型之工厂模式

说明

工厂模式总共分为3种,1.简单工厂模式(Simple Factory Pattern) 2.工厂方法(Factory Method Pattern) 3.抽象工厂模式(Abstract Factory Pattern),这篇文章会展示3种不同的工厂模式的差异和写法。

定义

  • 定义:定义一个创建对象接口
    但让视线这个接口的类来决定实例化哪个类
    工厂方法让类的实例化推迟到子类中进行
  • 类型:创建型

适用场景

  • 创建对象需要大量重复代码
  • 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
  • 一个类通过其子类来制指定创建哪个对象

优点

  • 用户只需要关系产品对应的工厂,无需关心创建细节
  • 加入新产品符合开闭原则,提高可扩展性

缺点

  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度

工厂模式中的角色

简单工厂角色说明

  • Product(产品)
    • Product角色属于框架房,是一个抽象类,是对创建类的一个具体抽象。
  • ConcreteProduct(实际的产品)
    • ConcreteCreator角色属于具体的实际加工方,它是实际工厂创建的实际产品。
  • ConcreteCreator(实际的创建者)
    • ConcreteCreator角色属于实际加工方,它负责生产实际的产品。

简单工厂类图

工厂方法角色说明

  • Product(产品)
    • Product角色属于框架房,是一个抽象类,是对创建类的一个具体抽象。
  • Creator(创建者)
    • Creator角色属于框架房,它是负责生成Product角色的抽象类,但具体的处理是由子类ConcreteCreator角色决定。
  • ConcreteProduct(实际的产品)
    • ConcreteCreator角色属于具体的实际加工方,它是实际工厂创建的实际产品。
  • ConcreteCreator(实际的创建者)
    • ConcreteCreator角色属于实际加工方,它负责生产实际的产品。

工厂方法类图

抽象工厂角色说明

  • AbstractProduct(抽象产品)
    • AbstractProduct角色负责定义AbstractFactory角色所生成的抽象零件和产品接口。
  • AbstractFactory(抽象工厂)
    • AbstractFactory角色负责定义用于生成抽象产品的接口。
  • ConcreteProduct(实际产品)
    • ConcreteProduct角色负责实现AbstractProduct角色的接口。
  • ConcreteFactory(实际工厂)
    • ConcreteFactory角色负责实现AbstractFactory角色的接口。

抽象工厂类图

代码实现

1. 简单工厂模式写法一

第一步,写一个Book接口,对应角色中Product

public interface Book {
    /**
     * 读书
     */
    void read();
}

第二步,写Book的实现类JavaBook,对应角色中ConcreteProduct

public class GoBook implements Book{
    @Override
    public void read() {
        System.out.println("写一本Go从入门到精通");
    }
}

第三步,再写一个Book的实现类PythonBook

public class GoBook implements Book{
    @Override
    public void read() {
        System.out.println("写一本Go从入门到精通");
    }
}

第四步,写简单工厂类

public class BookFactory {
    private final String javaBook = "java";
    private final String goBook = "go";
    public Book createBook(String name) {
        if (javaBook.equalsIgnoreCase(name)) {
            return new JavaBook();
        }else if (goBook.equalsIgnoreCase(name)){
            return new GoBook();
        }else {
            return null;
        }
    }
}

最后,写简单工厂测试类

public class SimpleFactoryTest {
    public static void main(String[] args) {
        BookFactory bookFactory = new BookFactory();
        Book javaBook = bookFactory.createBook("java");
        javaBook.read();
    }
}

1.1 简单工厂模式执行结果

执行简单工厂测试结果

2. 简单工厂写法二

简单工厂写法一在增加Book的时候,每次都需要根据产品的增加修改代码逻辑,不符合开闭原则,因此可以使用反射来优化,优化代码前三步都是相同,知识在工厂方法实现方式上不同,我们直接跳到第四步工厂方法的实现

public class BookFactory {
    public Book createBook(String className) {
        try {
            if (className != null && className.length() > 0) {
                return (Book) Class.forName(className).newInstance();
            }
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

第五步,简单工厂写法二测试实现类相同

public class SimpleFactoryTest {
    public static void main(String[] args) {
        BookFactory bookFactory = new BookFactory();
        Book javaBook = bookFactory.createBook(JavaBook.class.getName());
        javaBook.read();
    }
}

2.1 简单工厂写法二执行结果

可以看到简单工厂写法二执行结果和写法一相同,但写法二符合开闭原则。

3. 工厂方法

工厂方法模式的写法中前三步与简单工厂模式中相同,这里就不重复赘述了,那我们从第四步开始写。
第四步,声明一个BookFactory接口,就是角色中的Creator

public interface BookFactory {
    Book create();
}

第五步,实现一个JavaBookFacotory,也就是角色中的ConcreteCreator

public class JavaBookFactory implements BookFactory {

    @Override
    public Book create() {
        return new JavaBook();
    }
}

第六步,再实现一个GoBookFactory

public class GoBookFactory implements BookFactory {
    @Override
    public Book create() {
        return new GoBook();
    }
}

第七步,完成工厂方法测试类

public class FactoryMethodTest {
    public static void main(String[] args) {
        BookFactory javaBookFactory = new JavaBookFactory();
        Book javaBook = javaBookFactory.create();
        javaBook.read();
        System.out.println("\n"+"==========我是分割线========="+"\n");
        BookFactory goBookFactory = new GoBookFactory();
        Book goBook = goBookFactory.create();
        goBook.read();
    }
}

3.1 工厂方法模式执行结果

4. 抽象工厂模式

举个例子,我们读一本书,会将学习到的知识记录成笔记,但是我们的笔记可能包含好几个部分,比如书上的笔记(BookNote),笔记本上记录的笔记(Note)以及电脑中的学习笔记(ENote)。
第一步,先创建BookNote,NoteENote接口或抽象类,在类图中是AbstractProduct角色。

public interface ENote {
    void typing();
}
public interface BookNote {
    void mark();
}
public interface Note {
    void write();
}

第二步,分别创建三者实现类,在类图中是ConcreteProduct角色。

public class JavaBookNote implements BookNote{
    @Override
    public void mark() {
        System.out.println("在Java从入门到精通上标注了一段话!");
    }
}
public class JavaENote implements ENote{
    @Override
    public void typing() {
        System.out.println("在电脑上敲了一段java笔记");
    }
}
public class JavaNote implements Note {
    @Override
    public void write() {
        System.out.println("在笔记本上写了一段java笔记");
    }
}
public class GoBookNote implements BookNote{
    @Override
    public void mark() {
        System.out.println("在Go从入门到精通上标注了一段话!");
    }
}
public class GoENote implements ENote{
    @Override
    public void typing() {
        System.out.println("在电脑上敲了一段go笔记");
    }
}
public class GoNote implements Note {
    @Override
    public void write() {
        System.out.println("在笔记本上写了一段Go笔记");
    }
}

第三步,创建抽象工厂接口/抽象类,在类图中是AbstractFactory角色。

public interface NoteFactory {
    /**
     * 创建图书笔记
     * @return
     */
    BookNote createBookNote();

    /**
     * 创建电子笔记
     * @return
     */
    ENote createENote();

    /**
     * 创建笔记本笔记
     * @return
     */
    Note createNote();
}

第四步,创建抽象工厂实现类,在类图中是ConcreteFactory角色。

public class JavaNoteFactory implements NoteFactory{
    @Override
    public BookNote createBookNote() {
        return new JavaBookNote();
    }

    @Override
    public ENote createENote() {
        return new JavaENote();
    }

    @Override
    public Note createNote() {
        return new JavaNote();
    }
}
public class GoNoteFactory implements NoteFactory{
    @Override
    public BookNote createBookNote() {
        return new GoBookNote();
    }

    @Override
    public ENote createENote() {
        return new GoENote();
    }

    @Override
    public Note createNote() {
        return new GoNote();
    }
}

第五步,创建抽象工厂测试类

public class AbstractFactoryTest {
    public static void main(String[] args) {
        NoteFactory javaNoteFactory = new JavaNoteFactory();
        
        BookNote javaBookNote = javaNoteFactory.createBookNote();
        ENote javaENote = javaNoteFactory.createENote();
        Note javaNote = javaNoteFactory.createNote();
        
        javaBookNote.mark();
        javaENote.typing();
        javaNote.write();

        System.out.println("\n"+"==========我是分割线========="+"\n");
        NoteFactory goNoteFactory = new GoNoteFactory();
        
        BookNote goBookNote = goNoteFactory.createBookNote();
        ENote goENote = goNoteFactory.createENote();
        Note goNote = goNoteFactory.createNote();
        
        goBookNote.mark();
        goENote.typing();
        goNote.write();
        
    }
}

4.1 执行结果

0人推荐
随时随地看视频
慕课网APP