设计模式与范式 --- 创建型模式(工厂模式)

简介: 设计模式与范式 --- 创建型模式(工厂模式)

1.写在前



在介绍工厂模式之前,我们先思考如下场景:


有一天,林同学准备去买笔记本,他到商城发现有两款电脑他特别喜欢, 一款是 Macbook Pro, 另一款是 Surface Pro。


根据以上的场景,类图可以如下表示:


image.png

原始场景


代码实现:

interface Computer {
    public void printComputer();
}
class MacbookProComputer implements Computer {
    public void printComputer() {
        System.out.println("This is a macbook pro");
    }
}
class SurfaceBookComputer implements Computer {
    public void printComputer() {
        System.out.println("This is a surface book");
    }
}
public class Client {
    public void buy(Computer c){
        c.printComputer();
    }
    public static void main(String[] args) {
        Client c = new Client();
        c.buy(new SurfaceBookComputer());
    }
}


这时候问题就来了,客户只关心得到电脑,并不关心电脑是如何被生产出来的,假设这里电脑是由鼠标,键盘和显示器组成,那么我们还需要先创建这些类实例,才能创建电脑。

Keyboard keyboard = new Keyboard();
Display display = new Display();
Mouse mouse = new Mouse();
Client c = new Client();
c.buy(new SurfaceBookComputer(keyboard, display, mouse));


显然商家在卖电脑的时候不会要求客户自己把电脑组装好的吧。


2. 简单工厂模式



简单工厂模式:专门定义一个类用来创建其它类的实例,被创建的实例通常都具有共同的父类。


这里我们相当于是创建生产电脑的工厂,客户需要购买什么样的电脑,只要输入类型编号就可以获取该电脑,而无需知道该电脑是如何被生产出来的。


image.png

简单工厂模式


代码实现:

// 抽象产品类(接口)
interface Computer {
    public void printComputer();
}
// 具体产品类
class MacbookProComputer implements Computer {
    public void printComputer() {
        System.out.println("This is a macbook pro");
    }
}
class SurfaceBookComputer implements Computer {
    public void printComputer() {
        System.out.println("This is a surface book");
    }
}
// 创建电脑的工厂类(工厂角色)
class ComputerFactory {
    public Computer createComputer(String type) {
        Computer c = null;
        if(type.equals("macbook")) {
            c = new MacbookProComputer();
        }else if(type.equals("surface")) {
            c = new SurfaceBookComputer();
        }
        return c;
    }
}
public class Client {
    public void buy(Computer c){
        System.out.println("I buy a computer");
        c.printComputer();
    }
    public static void main(String[] args) {
        Client c = new Client();
        // 创建电脑的工厂类
        ComputerFactory cf = new ComputerFactory();
        Computer computer = cf.createComputer("macbook");
        c.buy(computer);
    }
}


工厂模式的角色一般包括:


  1. 工厂角色: 如上图的 ComputerFactory,它可以被客户端调用,其内部用于负责创建具体的对象。
  2. 抽象产品类:如上图的 Computer,它描述了所有实例的公共接口。
  3. 具体产品类:如上图的 MacbookProComputer,实现抽象产品的接口,是工厂角色中要创建的具体实例。


简单工厂模式的优点【工厂角色负责产生具体的实例对象,所以在工厂类中需要有必要的逻辑,通过客户的输入能够得到具体创建的实例;所以客户端就不需要感知具体对象是如何产生的,只需要将必要的信息提供给工厂即可。】


这时候负责这个工厂的产品经理说该工厂需要生产新的产品 Macbook Air, 那么该方法的缺点就暴露显现,一般工厂生产方法和具体产品实现一般是由不同工程师开发的,那么如果实现产品的工程师早早实现了新产品而工厂方法却一直没有更新,那么该产品就一直无法上架。其次代码耦合度太高,如果工厂方法由新来的工程师去修改的话,那么他又得先读懂源代码,效率显得低下。


所以简单工厂模式的缺点:简单工厂模式是违反“开闭原则”,即对扩展开放,对修改关闭;因为如果要新增具体产品,就需要修改工厂类的代码。


针对简单工厂模式暴露出来的弊端,我们需要对代码再进行改进,由此延伸出工厂方法模式。


3. 工厂方法模式



工厂方法模式:定义一个用来创建对象的接口,让子类决定实例化哪一个类,让子类决定实例化延迟到子类。


工厂方法模式是针对每个产品提供一个工厂类,在客户端中判断使用哪个工厂类去创建对象。


我们将之前的 ComputerFactory 抽象成一个接口,那么创建相应具体的工厂类去实现该接口的方法。


具体类图的实现:


image.png

工厂方法模式


代码实现:

// 抽象产品类(接口)
interface Computer {
    public void printComputer();
}
// 具体产品类
class MacbookProComputer implements Computer {
    public void printComputer() {
        System.out.println("This is a macbook pro");
    }
}
class SurfaceBookComputer implements Computer {
    public void printComputer() {
        System.out.println("This is a surface book");
    }    
}
// 工厂角色:所有实例(创建电脑)的公共接口
interface ComputerFactory {
    public Computer createComputer();
}
// 具体实例化的工厂类
class MsFactory implements ComputerFactory {
    public Computer createComputer(){
        return new SurfaceBookComputer();
    }
}
class AppleFactory implements ComputerFactory {
    public Computer createComputer() {
        return new MacbookProComputer();
    }
}
public class Client {
    public void buy(Computer c){
        System.out.println("I buy a computer");
        c.printComputer();
    }
    public static void main(String[] args) {
        Client c = new Client();
        // 用户根据需要创建对应的实例
        ComputerFactory cf = new AppleFactory();
        Computer computer = cf.createComputer();
        c.buy(computer);
    }
}


4.抽象工厂模式



这时候负责该工厂的产品经理说要生产新的一类产品操作系统 Mac Os 和 Windows 8,这时候就引申出了抽象工厂模式。


抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。


工厂方法模式和抽象工厂模式基本类似,可以这么理解:当工厂只生产一个产品的时候,即为工厂方法模式,而工厂如果生产两个或以上的商品即变为抽象工厂模式。


我们在抽象工厂接口中新增创建系统的方法,并由实例工厂类去实现。


类图可由下表示:


image.png

抽象工厂模式


代码实现:

// 抽象产品类(接口)
interface Computer {
    public void printComputer();
}
// 具体产品类
class MacbookProComputer implements Computer {
    public void printComputer() {
        System.out.println("This is a macbook pro");
    }
}
class SurfaceBookComputer implements Computer {
    public void printComputer() {
        System.out.println("This is a surface book");
    }
}
// 工厂角色:所有实例(操作系统)的公共接口
interface OperatingSystem {
    public void printSystem();
}
// 实例化的工厂类
class MacOsSystem implements OperatingSystem {
    public void printSystem() {
        System.out.println("This is a mac os");
    }
}
class Windows8System implements OperatingSystem {
    public void printSystem() {
        System.out.println("This is a window 8");
    }
}
// 抽象工厂:提供一系列相关或者相互依赖对象的接口!
interface ProductionFactory {
    public Computer createComputer();
    public OperatingSystem createSystem();
}
// 实例化抽象工厂
class AppleFactory implements ProductionFactory {
    public Computer createComputer() {
        return new MacbookProComputer();
    }
    public OperatingSystem createSystem() {
        return new MacOsSystem();
    }
}
class MsFactory implements ProductionFactory {
    public Computer createComputer() {
        return new SurfaceBookComputer();
    }
    public OperatingSystem createSystem() {
        return new Windows8System();
    }
}
public class Client {
    public void buy(Computer c){
        System.out.println("I buy a computer");
        c.printComputer();
    }
    public void use(OperatingSystem s) {
        System.out.println("Operating System");
        s.printSystem();
    }
    public static void main(String[] args) {
        // 创建一个抽象工厂的实现类
        ProductionFactory pf = new AppleFactory();
        // 创建具体工厂的实现类
        Computer c = pf.createComputer();
        OperatingSystem s = pf.createSystem();
        Client client = new Client();
        client.buy(c);
        client.use(s);
    }
}


抽象工厂模式的缺点在于产品类的扩展,将会是十分费力的,假如在需要加入新的产品,那么几乎所有的工厂类都需要进行修改,所以在使用抽象工厂模式时,对产品等级结构的划分是十分重要的。


5.总结



总结工厂模式的概念:


  • 简单工厂模式:专门定义一个类用来创建其它类的实例,被创建的实例通常都具有共同的父类。即一个抽象产品类,可以派生出多个具体产品类。一个具体工厂类,通过往此工厂传入不同参数,产出不同的具体产品类实例。
  • 工厂方法模式:定义一个用来创建对象的接口,让子类决定实例化哪一个类,让子类决定实例化延迟到子类。即一个抽象产品类,可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。每个具体工厂类只能创建一个具体产品类的实例。
  • 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。即多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。


三种模式的对比:


  • 抽象工厂模式和工厂方法模式


工厂方法模式针对单独(一种)产品的创建,而抽象工厂模式注重一个产品系列的创建。如果产品系列只有一个产品的话,那么抽象工厂模式就是工厂方法模式了。在抽象工厂中使用工厂方法来提供具体实现,这个时候他们联合使用。


  • 工厂模式和简单工厂


两者非常类似,都是用来做选择实现的。不同的地方在于简单工厂在自身就做了选择实现。而工厂方法模式则是把实现延迟到子类执行。如果把工厂方法的选择实现直接在父类实现,那么此时就退化为简单工厂方法模式了。


  • 简单工厂和抽象工厂


简单工厂用于做选择实现,每个产品的实现之间没有依赖关系。而抽象工厂实现的一个产品系列,相互之间有关联。这是他们的区别。


无论是简单工厂模式,工厂方法模式还是抽象工厂模式,它们都具有类似的特性,适用场景也十分类似,都是封装对象的创建,最终目的都是为了【解耦】

综合上述三种工厂模式,我们可以发现,使用工厂模式时,只需要关心降低耦合度的目的是否达到了。使用工厂方法后,调用端的耦合度大大降低了。并且对于工厂来说,是可以扩展的,以后如果想组装其他的产品,只需要再增加一个工厂类的实现就可以。无论是灵活性还是稳定性都得到了极大的提高。


6.参考



https://zhuanlan.zhihu.com/p/24650116

https://www.jianshu.com/p/ea18c082b5dd

https://www.jianshu.com/p/81ceb0275c22

相关文章
|
2月前
|
设计模式 Java
【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)
【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)
56 2
|
3月前
|
设计模式
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
这篇文章详细解释了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。每种模式都通过代码示例展示了其应用场景和实现方法,并比较了它们之间的差异。简单工厂模式通过一个工厂类来创建各种产品;工厂方法模式通过定义一个创建对象的接口,由子类决定实例化哪个类;抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不需要明确指定具体类。
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
|
4月前
|
设计模式 存储 负载均衡
【五】设计模式~~~创建型模式~~~单例模式(Java)
文章详细介绍了单例模式(Singleton Pattern),这是一种确保一个类只有一个实例,并提供全局访问点的设计模式。文中通过Windows任务管理器的例子阐述了单例模式的动机,解释了如何通过私有构造函数、静态私有成员变量和公有静态方法实现单例模式。接着,通过负载均衡器的案例展示了单例模式的应用,并讨论了单例模式的优点、缺点以及适用场景。最后,文章还探讨了饿汉式和懒汉式单例的实现方式及其比较。
【五】设计模式~~~创建型模式~~~单例模式(Java)
|
4月前
|
设计模式 Java
Java 设计模式之谜:工厂模式与抽象工厂模式究竟隐藏着怎样的神奇力量?
【8月更文挑战第30天】在Java编程中,设计模式为常见问题提供了高效解决方案。工厂模式与抽象工厂模式是常用的对象创建型设计模式,能显著提升代码的灵活性、可维护性和可扩展性。工厂模式通过定义创建对象的接口让子类决定实例化哪个类;而抽象工厂模式则进一步提供了一个创建一系列相关或相互依赖对象的接口,无需指定具体类。这种方式使得系统更易于扩展和维护。
43 1
|
4月前
|
设计模式 算法 开发者
深入理解工厂模式与策略模式:设计模式的灵活应用
深入理解工厂模式与策略模式:设计模式的灵活应用
|
4月前
|
设计模式 XML 存储
【三】设计模式~~~创建型模式~~~抽象工厂模式(Java)
文章详细介绍了抽象工厂模式,这是一种创建型设计模式,用于提供一个接口以创建一系列相关或相互依赖的对象,而不指定它们具体的类。通过代码示例和结构图,文章展示了抽象工厂模式的动机、定义、结构、优点、缺点以及适用场景,并探讨了如何通过配置文件和反射机制实现工厂的动态创建。
【三】设计模式~~~创建型模式~~~抽象工厂模式(Java)
|
4月前
|
设计模式 XML 存储
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
文章详细介绍了工厂方法模式(Factory Method Pattern),这是一种创建型设计模式,用于将对象的创建过程委托给多个工厂子类中的某一个,以实现对象创建的封装和扩展性。文章通过日志记录器的实例,展示了工厂方法模式的结构、角色、时序图、代码实现、优点、缺点以及适用环境,并探讨了如何通过配置文件和Java反射机制实现工厂的动态创建。
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
|
4月前
|
设计模式 XML Java
【一】设计模式~~~创建型模式~~~简单工厂模式(Java)
文章详细介绍了简单工厂模式(Simple Factory Pattern),这是一种创建型设计模式,用于根据输入参数的不同返回不同类的实例,而客户端不需要知道具体类名。文章通过图表类的实例,展示了简单工厂模式的结构、时序图、代码实现、优缺点以及适用环境,并提供了Java代码示例和扩展应用,如通过配置文件读取参数来实现对象的创建。
【一】设计模式~~~创建型模式~~~简单工厂模式(Java)
|
4月前
|
设计模式 uml C语言
设计模式----------工厂模式之简单工厂模式(创建型)
这篇文章详细介绍了简单工厂模式,包括其定义、应用场景、UML类图、通用代码实现、运行结果、实际应用例子,以及如何通过反射机制实现对象创建,从而提高代码的扩展性和维护性。
设计模式----------工厂模式之简单工厂模式(创建型)
|
4月前
|
设计模式 uml
设计模式-------------工厂模式之工厂方法模式(创建型)
工厂方法模式是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而实现类的实例化推迟到子类中进行,提高了系统的灵活性和可扩展性。