其他
Java设计模式—工厂模式(factory pattern)
工厂模式(Factory Pattern)是Java中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
工厂模式分为三类,如下:
1)简单工厂模式(Simple Factory
),又称静态工厂方法模式,是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的, 不利于产生系列产品;
2)工厂方法模式(Factory Method
),又称为多形性工厂是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成;
3)抽象工厂模式(Abstract Factory
),又称为工具箱,提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构,产生产品族但不利于产生新的产品,而工厂方法模式针对的是一个产品的等级结构。
1、简单工厂模式
简单工厂模式又称静态工厂方法模式,在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定那一个产品类应当被实例化, 如同一个交通警察站在来往的车辆流中,决定放行那一个方向的车辆向那一个方向流动一样。它的具体组成如下:
1)工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品。
2)抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
3)具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
下面举例猫与狗吃饭的故事,具体代码实现如下:
(1)创建共用接口,代码如下:
package com.yoodb;
public interface Dinner{
public void eat();
}
(2)创建实现类,代码如下:
package com.yoodb;
public class CatDinner implements Dinner{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("小猫来吃饭了!");
}
}
package com.yoodb;
public class DogDinner implements Dinner{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("小狗来吃饭了!");
}
}
(3)创建工厂,代码如下:
package com.yoodb;
public class DinnerFactory {
public Dinner produce(String animal){
if(animal.equals("cat")){
return new CatDinner();
}else if(animal.equals("dog")){
return new DogDinner();
}else{
System.out.println("请输入存在的动物!");
return null;
}
}
}
或者静态化,代码如下:
package com.yoodb;
public class DinnerFactory {
public static Dinner produce(String animal){
if(animal.equals("cat")){
return new CatDinner();
}else if(animal.equals("dog")){
return new DogDinner();
}else{
System.out.println("请输入存在的动物!");
return null;
}
}
}
(4)main函数测试,代码如下:
package com.yoodb;
public class FactoryTest {
public static void main(String[] args) {
DinnerFactory factory = new DinnerFactory();
Dinner dinner = factory.produce("cat");
dinner.eat();
}
}
或者静态化调用,代码如下:
package com.yoodb;
public class FactoryTest {
public static void main(String[] args) {
Dinner dinner = DinnerFactory.produce("cat");
dinner.eat();
}
}
2、工厂方法模式
工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。它的组成具体如下:
1)抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。可以看出工厂角色的结构也是符合开闭原则的!
(1)将上述简单工厂模式中创建工厂类,进行如下变动代码如下:
package com.yoodb;
public class DinnerFactory {
public Dinner catProduce(){
return new CatDinner();
}
public Dinner dogProduce(){
return new DogDinner();
}
}
(2)main函数测试,代码如下:
package com.yoodb;
public class FactoryTest {
public static void main(String[] args) {
DinnerFactory factory = new DinnerFactory();
Dinner dinner = factory.produce("cat");
dinner.eat();
}
}
3、抽象工厂模式
(1)创建共用接口,代码如下:
package com.yoodb;
public interface Dinner{
public void eat();
}
(2)创建实现类,代码如下:
package com.yoodb;
public class CatDinner implements Dinner{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("小猫来吃饭了!");
}
}
package com.yoodb;
public class DogDinner implements Dinner{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("小狗来吃饭了!");
}
}
(3)创建接口,代码如下:
package com.yoodb;
public interface Provider {
public Sender produce();
}
(4)创建两个工厂,代码如下:
package com.yoodb;
public class CatFactory implements Provider{
public Dinner produce(){
return new CatDinner();
}
}
package com.yoodb;
public class DogFactory implements Provider{
public Dinner produce(){
return new DogDinner();
}
}
(5)main函数测试,代码如下:
package com.yoodb;
public class FactoryTest {
public static void main(String[] args) {
Provider factory = new DogFactory();
Dinner dinner = factory.produce();
dinner.eat();
}
}
4、工厂模式应用场景
工厂方法:
在以下情况下,适用于工厂方法模式:
(1) 当一个类不知道它所必须创建的对象的类的时候。
(2) 当一个类希望由它的子类来指定它所创建的对象的时候。
(3) 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
抽象工厂:
(1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
(2)这个系统有多于一个的产品族,而系统只消费其中某一产品族。
(3)同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
(4)系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
推荐阅读
Docker(二):理解容器编排工具Kubernetes内部工作原理
互联网大厂Java面试题集—Spring boot常见面试题(二)
互联网大厂Java面试题集—Spring boot面试题(一)
JDK1.7中HashMap死环问题及JDK1.8中对HashMap的优化源码详解
Shiro应用篇(二):Shiro结合Redis实现分布式环境下的Session共享
微框架Spring Boot使用Redis如何实现Session共享
Java面试高级篇—Dubbo与Zookeeper面试题16期
关注微信公众号“Java精选”(w_z90110),回复关键词领取资料:如Hadoop,Dubbo,CAS源码等等,免费领取资料视频和项目。
涵盖:程序人生、搞笑视频、算法与数据结构、黑客技术与网络安全、前端开发、Java、Python、Redis缓存、Spring源码、各大主流框架、Web开发、大数据技术、Storm、Hadoop、MapReduce、Spark、elasticsearch、单点登录统一认证、分布式框架、集群、安卓开发、iOS开发、C/C++、.NET、Linux、Mysql、Oracle、NoSQL非关系型数据库、运维等。