一、概述
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
简单来说:工厂就是一种创建型的设计模式,常用于封装变化,一般遵循那里有变化就封装那里的原则。这里我们以一个快餐店为示例讲解,FastFood表示快餐,KFC表示肯德基,Mac表示麦当劳。
FastFood.java代码如下:
package com.Design_mode.Factory_pattern; //快餐 public abstract class FastFood { //品牌 public String brand; //展示 public abstract void show(); }
KFC.java代码如下:
package com.Design_mode.Factory_pattern; public class KFC extends FastFood { @Override public void show() { this.brand = "肯德基"; System.out.println("欢迎来到"+ this.brand); } }
Mac.java代码如下:
package com.Design_mode.Factory_pattern; public class Mac extends FastFood { @Override public void show() { this.brand = "麦当劳"; System.out.println("欢迎来到"+ this.brand); } }
Student.java代码如下:
package com.Design_mode.Factory_pattern; public class Student { public static void main(String[] args) { KFC kfc = new KFC(); kfc.show(); } }
运行结果:
从Student类中可以看到学生只允许吃KFC,如果他想吃别的东西就不允许了,违背DIP(依赖倒转原则),解决:
package com.Design_mode.Factory_pattern; public class Student { public static void main(String[] args) { //这里可以指定任意FastFood子类,LSP //如果这里是稳定的,不会经常变化,则代码是没有问题的 //如果这里要不断的变化,new KFC(),new Mac,new Kongfu()... FastFood kfc = new KFC(); kfc.show(); } }
new KFC()就是一个变化点,封装。
二、简单工厂(Simple Factory)
简单工厂并不是GOF所著的书中提出的一种设计模式,但这种模式是学习设计模式一个很好的入口点,让我们能更容易理解设计模式是如何达到设计原则的要求的。
简单工厂设计模式是一种创建型的模式,主要是用来解决对象的创建问题。
上面的类图反映的就是将一组相似对象(继承自同一个类)的实例的创建放到另外一个对象中完成,即通过 ProductFactory 这个类来按需创建对象
在第一节中我们提出了“封装变化”的概念,这里使用简单工厂解决问题,代码如下:
FastFoodFactory.java代码如下:
package com.Design_mode.Factory_pattern; /** * 快餐工厂 */ public class FastFoodFactory { /*** * 用于实现不同类型快餐品牌的创建 * @param brand 类型 * @return 快餐品牌 */ public static FastFood GetFastFood(String brand) { switch (brand) { case "KFC": return new KFC(); case "Mac": return new Mac(); default: throw new IllegalArgumentException("没有该品牌"); } } }
Student.java代码如下
package com.Design_mode.Factory_pattern; import java.util.Scanner; public class Student { public static void main(String[] args) { //这里可以指定任意FastFood子类,LSP //如果这里是稳定的,不会经常变化,则代码是没有问题的 //如果这里要不断的变化,new KFC(),new Mac,new Kongfu()... Scanner input=new Scanner(System.in); System.out.print("您想吃什么:"); String brand=input.next(); FastFood kfc = FastFoodFactory.GetFastFood(brand); kfc.show(); } }
运行结果:
简单工厂的优点:
简单工厂的工厂类中包含了必要的逻辑判断,这样就可以根据客户端的选择条件来动态的实例化相关的类,对于客户端来说,其去除了与具体产品之间的依赖
简单工厂的缺点:
违背了开-闭原则
三、工厂方法(Factory Method)
工厂方法模式,定义了一个用于创建对象的接口,让子类来决定要实例化哪一个类,工厂方法让类把实例化延迟到其子类。
在工厂方法模式中主要有以下几个组成部分:
抽象工厂:是工厂方法模式的核心,任何在模式中创建的具体工厂必须实现这个接口。
具体工厂:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品:方法方法模式所要创建的对象的父类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品:这是实现了抽象产品所定义的接口的具体产品类的实例。这是客户端最终需要的东西。
示例:
KFC肯德基,Mac麦当劳,Chips薯条,Ham汉堡
Chips.java代码如下:
package com.Design_mode.Factory_pattern; /** * 抽象产品,薯条 */ public abstract class Chips { /** * 显示薯条信息 */ public abstract void info(); }
KFCChips.java代码如下:
package com.Design_mode.Factory_pattern; public class KFCChips extends Chips { @Override public void info() { System.out.println("肯德基薯条"); } }
MacChips.java代码如下:
package com.Design_mode.Factory_pattern; public class MacChips extends Chips { @Override public void info() { System.out.println("麦当劳薯条"); } }
Ham.java代码如下:
package com.Design_mode.Factory_pattern; /** * 抽象产品,汉堡 */ public abstract class Ham { /** * 显示汉堡信息 */ public abstract void show(); }
KFCHam.java代码如下:
package com.Design_mode.Factory_pattern; public class KFCHam extends Ham { @Override public void show() { System.out.println("肯德基汉堡"); } }
MacHam.java代码如下:
package com.Design_mode.Factory_pattern; public class MacHam extends Ham { @Override public void show() { System.out.println("麦当劳汉堡"); } }
FastFoodFactoryAb.java代码如下:
package com.Design_mode.Factory_pattern; /** * 抽象工厂 快餐工厂 */ public abstract class FastFoodFactoryAb { /** * 生产汉堡 */ public abstract Ham CreateHam(); /** * 生产薯条 */ public abstract Chips CreateChips(); /*** * 用于实现不同类型快餐品牌的创建 * @param brand 类型 * @return 快餐品牌 */ public static FastFoodFactoryAb GetFastFood(String brand) { switch (brand) { case "KFC": return new KFCFactory(); case "Mac": return new MacFactory(); default: throw new IllegalArgumentException("没有该品牌"); } } }
KFCFactory.java代码如下:
package com.Design_mode.Factory_pattern; public class KFCFactory extends FastFoodFactoryAb { @Override public Ham CreateHam() { return new KFCHam(); } @Override public Chips CreateChips() { return new KFCChips(); } }
MacFactory.java代码如下:
package com.Design_mode.Factory_pattern; public class MacFactory extends FastFoodFactoryAb { @Override public Ham CreateHam() { return new MacHam(); } @Override public Chips CreateChips() { return new MacChips(); } }
Student.java代码如下:
package com.Design_mode.Factory_pattern; import java.util.Scanner; public class Student { public static void main(String[] args) { //这里可以指定任意FastFood子类,LSP //如果这里是稳定的,不会经常变化,则代码是没有问题的 //如果这里要不断的变化,new KFC(),new Mac,new Kongfu()... Scanner input=new Scanner(System.in); System.out.print("您想吃什么:"); String brand=input.next(); FastFoodFactoryAb fastFood = FastFoodFactoryAb.GetFastFood(brand); fastFood.CreateHam().show(); fastFood.CreateChips().info(); } }
运行结果: