Java设计模式之工厂模式
前言
工厂模式在项目中被广泛的使用。使用设计模式,可以让很复杂的业务用简单的代码表达出来。
工厂模式的概述
首先我们举个栗子来说明,在相传的神话中,最早的一批人类是通过女娲造人来产生的,女娲就是一个客户端的调用方,也是场景的执行者。黄色人种,白色人种,黑色人种就是要产生的产品。即工厂中的产品。
我们再来定义一个抽象工厂用来生成产品。示意代码如下所示:
1 public abstract class AbstractHumanFactory { 2 3 public abstract <T extends Human> T createHuman(Class<T> c); 4 }
其中入参是人类的类型,出参是对应的人类。接下来我们来定义一下具体的人类。首先新增一个人类的抽象接口以及具体的三种肤色的人类,如下代码示意:
1 public interface Human { 2 3 public void getColor(); 4 5 public void talk(); 6 }
1 public class BlackHuman implements Human { 2 @Override 3 public void getColor() { 4 5 System.out.println("我是黑人"); 6 7 } 8 9 @Override 10 public void talk() { 11 System.out.println("黑人会说话"); 12 } 13 }
1 public class WhiteHuman implements Human { 2 @Override 3 public void getColor() { 4 System.out.println("我是白人"); 5 6 } 7 8 @Override 9 public void talk() { 10 System.out.println("白人会说话"); 11 12 } 13 }
public class YellowHuman implements Human { @Override public void getColor() { System.out.println("我是黄人"); } @Override public void talk() { System.out.println("黄人会说话"); } }
最后我们新增一个抽象工程的具体工厂方法。如下代码所示:
1 public class HumanFactory extends AbstractHumanFactory { 2 @Override 3 public <T extends Human> T createHuman(Class<T> c) { 4 Human human = null; 5 try { 6 human = (T)Class.forName(c.getName()).newInstance(); 7 } catch (Exception e) { 8 9 } 10 return (T)human; 11 } 12 }
最后我们新增一个场景类Client:
public class Client { public static void main(String[] args) { AbstractHumanFactory humanFactory = new HumanFactory(); BlackHuman blackHuman = humanFactory.createHuman(BlackHuman.class); blackHuman.getColor(); blackHuman.talk(); WhiteHuman whiteHuman = humanFactory.createHuman(WhiteHuman.class); blackHuman.getColor(); blackHuman.talk(); YellowHuman yellowHuman = humanFactory.createHuman(YellowHuman.class); yellowHuman.getColor(); yellowHuman.talk(); } }
运行结果如下所示:
我是黑人
黑人会说话
我是黑人
黑人会说话
我是黄人
黄人会说话
工厂模式的定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到子类。
总结一下,在工程模式中,我们拥有客户端,也就是调用方。同时拥有工厂接口和具体的工厂实现。另外还包含产品接口和具体产品。
1.采用工厂模式,只要客户端知道要产生什么产品整套链路就确认下来了,无须知晓产品产生的细节。这降低了模块之间的耦合。
2.当增加一个产品,只需要实现产品接口即可,工厂类不需要任何的变动。这符合设计原则中的开闭的原则。对修改关闭,对扩展开放。
最后我们再来总结一下工厂模式的通用实现方式:
①首先我们需要有抽象产品类,同时拥有公共的方法prepare();以及抽象的处理方法handle();
1 package com.example.pattern.factory.summary; 2 3 public abstract class AbstractProduct { 4 5 public void prepare() { 6 7 } 8 9 10 public abstract void handle(); 11 }
②需要有具体的产品类,这些产品类继承了抽象产品类,重写的handle抽象方法。
1 package com.example.pattern.factory.summary; 2 3 public class ConcreteProductFirst extends AbstractProduct { 4 5 6 @Override 7 public void handle() { 8 9 } 10 }
这样的产品类可以有多个,主要用来负责产品的产生,但是要保证这个产品是一个具体的产品。
③抽象工厂类
1 package com.example.pattern.factory.summary; 2 3 public interface IFactory { 4 5 public <T extends AbstractProduct> T createProduct(Class<T> clazz) ; 6 7 }
抽象工厂类可以定义为接口,也可以定义为抽象类。在实际中可以采用定义一个接口,一个抽象类实现这个接口,把公共的实现方法抽取到抽象类中实现,具体的工厂类再去继承这个抽象工厂。
④具体工厂类
1 package com.example.pattern.factory.summary; 2 3 public class ConcreteFactory implements IFactory { 4 @Override 5 public <T extends AbstractProduct> T createProduct(Class<T> clazz) { 6 7 AbstractProduct product = null; 8 9 try { 10 product = (AbstractProduct)Class.forName(clazz.getName()).newInstance(); 11 } catch (Exception e) { 12 13 } 14 15 return (T)product; 16 } 17 }
⑤业务场景类
1 package com.example.pattern.factory.summary; 2 3 public class Client { 4 5 public static void main(String[] args) { 6 IFactory factory = new ConcreteFactory(); 7 8 ConcreteProductFirst product = factory.createProduct(ConcreteProductFirst.class); 9 product.handle(); 10 11 } 12 }
以上代码是工厂模式的通用写法,在实际应用中可以适当调整,或者和其他的设计模式混合使用。