工厂模式是一种创建型模式,它提供了一种新的创建对象的方式,一般情况下我们都习惯用new关键字直接创建对象。有时候会遇到这种情况,我们需要根据具体的场景选择创建什么类型的对象,可能有多种类型都能选择,但一次只能选一种,针对这种对象可以选择性创建的情况工厂模式就显得十分好用了。工厂模式嘛,顾名思义就是一个很大的工厂,里面有各种我们需要的产品,我们可以根据自己的需求选择买哪种产品,只要告诉工厂我们想要的产品即可。还有一种是抽象工厂模式,这种模式中,我们请求一个具体的产品时,工厂会去找该对象所属类型的工厂要,然后再给我们,从用户角度来看就是一个工厂提供的产品,其实在其内部,产品并不是由它生产,而是由不同类别的具体工厂生产出来由它提供给用户,在这里其实我们所请求的这个工厂它不是一个具体的能生产各类产品的工厂,我们可以称之为抽象工厂,而通过这种工厂生产产品的模式就叫抽象工厂模式。抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。说起来有点绕。等会用具体的实例来说明。

一、工厂模式实例

举一个我们上网时经常遇到的例子,假如我们在用QQ音乐听歌,突然听到一首很喜欢的歌想分享一下,在我们选择分享对象的时候会有QQ空间、微信朋友圈以及微博三种选项,但是这时候我们只能选择其中之一进行分享,这就相当于我们需要选择一个对象创建并调用它的分享接口。此时我们可以创建一个工厂,这个工厂负责生产不同的社交圈对象,我们只需要告诉它社交圈的名称,它就能给我们创建对应的对象,而无需我们自己创建。这里的QQ空间、微信朋友圈和微博相当于三种社交类,让它们实现一个社交接口并实现里面的分享方法,这样通过工厂获取到对应的对象之后我们就能分享歌曲到对应的空间了。下面是代码实现过程。

第一步:创建一个社交软件接口,用来进行音乐分享

 /*
* 定义一个社交软件接口
*/
public interface ISocialSoftware {
//定义一个分享音乐的接口
public void shareMusic();
}

第二步:创建三个社交软件类,实现上面的接口

 /*
* 定义qq空间类实现社交软件接口
*/
public class Qqzone implements ISocialSoftware { public void shareMusic() {
System.out.println("分享到qq空间");
}
} /*
* 定义微博类,实现社交软件接口
*/
public class WeiBo implements ISocialSoftware { public void shareMusic() {
System.out.println("分享到微博");
} } /*
* 定义一个微信类,实现社交软件接口
*/
public class WeiXin implements ISocialSoftware { public void shareMusic() {
System.out.println("分享到微信朋友圈");
}
}

第三步:创建工厂类,用来创建不同的社交软件对象

 /*
* 创建一个社交软件工厂,提供不同的软件对象
*/
public class SocialSoftwareFactory { /*
* 获取社交软件对象
*/
public static ISocialSoftware getSocialSoftware(String softwareName) {
String name = softwareName;
ISocialSoftware software = null;
switch (name) {
case "qq":
software = new Qqzone();
break;
case "weibo":
software = new WeiBo();
break;
case "weixin":
software = new WeiXin();
break;
default:
System.out.println("找不到该软件");
} return software;
}
}

第四步:模拟用户将qq音乐分享到不同的社交圈

 /*
* 用户玩qq音乐分享音乐
*/
public class PlayQqMusic {
public static void main(String[] args) { // 获取工厂对象
SocialSoftwareFactory factory = new SocialSoftwareFactory();
//用户选择社交软件名称
String softwareName = "weixin";
//根据软件名称分别分享到不同社交软件
ISocialSoftware software = factory.getSocialSoftware(softwareName);
//用户只需修改软件名称,无需关心这个软件是怎么获取到的
software.shareMusic();
}
}

第五步:分享结果

 分享到微信朋友圈

在上面的例子中,调用工厂的getSocialSoftware(softwareName)方法,会按照指定的软件名称生成一个指向社交软件接口的对象,例如上面的微信,这样我们就能调用微信的音乐分享功能分享qq音乐到朋友圈了。

二、抽象工厂模式实例

以在淘宝购物为例,我们可以视淘宝中的服装类为一个大工厂,这个大类中又有女装、女鞋、男装、男鞋等不同的类别,相当于不同类别的服装工厂,而每一个小工厂中又有不同的衣服可以选择,如女装中有卫衣、连衣裙、针织衫三种;女鞋中有帆布鞋、运动鞋、靴子三种;男装中有西服、牛仔裤、运动套装三种;男鞋中有凉鞋、皮鞋、人字拖三种,现在我们通过淘宝服装店买某个衣服的时候,该店不会直接给我们一个具体的衣服,而是通过提供女装、女鞋、男装、男鞋店来让我们选择具体的商品,这里的淘宝服装店相当于一个抽象工厂,能生产女装、女鞋、男装、男鞋等不同的具体工厂,具体的工厂才能提供具体的商品给消费者,下面用代码实现这个例子:

为了简化,我卖女装和女鞋为例

第一步:创建女装、女鞋两个接口

 /*
* 定义一个女装接口
*/
public interface IWomanClothing {
//卖衣服
public void sail();
} /*
* 定义一个女鞋接口
*/
public interface IWomanShoes {
public void sail();
}

第二步:定义女装店和女鞋店,分别实现上述接口

不同女装店

 /*
* 定义一个卫衣店,实现女装接口,卖卫衣
*/
public class WeiClothingShop implements IWomanClothing { @Override
public void sail() {
System.out.println("出售卫衣");
} } /*
* 定义一个连衣裙店,实现女装接口,出售连衣裙
*/
public class DressShop implements IWomanClothing { @Override
public void sail() {
System.out.println("出售连衣裙");
} } /*
* 定义一个针织衫店,实现女装接口,出售针织衫
*/
public class SweaterShop implements IWomanClothing { @Override
public void sail() {
System.out.println("出售针织衫");
}
}

不同女鞋店

 /*
* 定义一个帆布鞋店,实现女鞋接口,出售帆布鞋
*/
public class ClothShoesShop implements IWomanShoes { @Override
public void sail() {
System.out.println("出售帆布鞋");
}
} /*
* 创建一个运动鞋商店,实现女鞋接口,出售运动女鞋
*/
public class SportsShoesShop implements IWomanShoes { @Override
public void sail() {
System.out.println("出售女运动鞋");
}
} /*
* 创建一个女靴店,实现女鞋接口,出售女靴
*/
public class BootsShop implements IWomanShoes { @Override
public void sail() {
System.out.println("出售女靴");
}
}

第三步:定义一个抽象工厂类,含有获取女装店和女鞋店的接口

 /*
* 创建一个抽象工厂,提供生产女装和女鞋的接口
*/
public abstract class AbstractFactory {
// 卖女装
public abstract IWomanClothing sailWomanClothing(String clothing); // 卖女鞋
public abstract IWomanShoes sailWomanShoes(String shoes);
}

第四步:定义一个女装工厂,继承上述抽象工厂,并获取女装实例

 /*
* 创建一个女装工厂,生产女装
*/
public class WomanClothingFactory extends AbstractFactory { @Override
public IWomanClothing sailWomanClothing(String clothing) {
IWomanClothing womanClothing = null;
switch (clothing) {
case "wei":
womanClothing = new WeiClothingShop();
break;
case "dress":
womanClothing = new DressShop();
break;
case "sweater":
womanClothing = new SweaterShop();
break;
default:
break;
}
return womanClothing;
} @Override
public IWomanShoes sailWomanShoes(String shoes) {
return null;
}
}

第五步:定义一个女鞋工厂,生产女鞋

 /*
* 创建一个女鞋工厂,生产女鞋
*/
public class WomanShoesFactory extends AbstractFactory { @Override
public IWomanShoes sailWomanShoes(String shoes) {
IWomanShoes womanShoes = null;
switch (shoes) {
case "cloth":
womanShoes = new ClothShoesShop();
break;
case "sports":
womanShoes = new SportsShoesShop();
break;
case "boots":
womanShoes = new BootsShop();
break;
default:
break;
}
return womanShoes;
} @Override
public IWomanClothing sailWomanClothing(String clothing) {
return null;
}
}

第六步:定义一个类用来生产实际工厂

 /**
* 创建一个工厂生产器
*/
public class FactoryProducer {
public static AbstractFactory produceFactory(String facName) {
AbstractFactory factory = null;
if (facName.equals("clothing")) {
factory = new WomanClothingFactory();
} else if (facName.equals("shoes")) {
factory = new WomanShoesFactory();
}
return factory;
}
}

第七步:定义一个消费者购物(重点看注释部分)

 /*
* 定义一个消费者购物
*/
public class Customer {
public static void main(String[] args) {
// 通过服装店买女装时
// 1、先定义一个女装名称,比如卫衣
String clothingName = "wei";
// 2、服装店先找到女装店:用户买衣服的时候并不知道服装店会通过女装店提供衣服
AbstractFactory clothingFactory = FactoryProducer.produceFactory("clothing");
// 3、然后由女装店把衣服提供给服装店
IWomanClothing clothingShop = clothingFactory.sailWomanClothing(clothingName);
clothingShop.sail(); // 通过服装店买女鞋时
// 1、先定义一个女鞋名称,比如运动鞋
String shoesName = "sports";
// 2、服装店先找到女鞋店:用户买鞋的时候并不知道服装店会通过女鞋店提供鞋子
AbstractFactory shoesFactory = FactoryProducer.produceFactory("shoes");
// 3、然后由女鞋店提供女鞋给服装店
IWomanShoes shoesShop = shoesFactory.sailWomanShoes(shoesName);
shoesShop.sail();
}
}

第八步:查看结果

 出售卫衣
出售女运动鞋

从结果可以看出,消费者买卫衣和运动鞋时,其实是它所面向的工厂通过卫衣厂和运动鞋厂提供卫衣和鞋,而不是由它自己生产,所以我们把消费者直接面对的这个工厂可以看成一个抽象工厂,它其实是不存在的。

以上就是工厂模式及代码实例,实际应用中还要根据具体业务逻辑进行优化。

Java内功修炼系列一工厂模式的更多相关文章

  1. Java内功修炼系列一代理模式

    代理模式是JAVA设计模式之一,网上设计模式相关的博文铺天盖地,参考它们有助于自己理解,但是所谓“尽信书不如无书”,在参考的同时也要思考其正确性,写博客也是为了记录自己理解知识点的思路历程和心路历程, ...

  2. Java内功修炼系列一责任链模式

    在上一节的拦截器中提到,程序的设计者一般会用拦截器替替代动态代理,将动态代理的逻辑隐藏起来,而把拦截器接口提供给开发者,使开发者不需要关系动态代理的具体实现过程,但是有时候需要多个拦截器,而且拦截器之 ...

  3. Java内功修炼系列一观察者模式

    观察者模式又称发布-订阅模式,就是观察者通过订阅被观察者,或关注被观察者,从而实时更新观察者的信息.比如我们玩微博的时候,如果关注了一些博主,那么当博主发动态时,在首页微博列表中就会自动更新这些博主发 ...

  4. Java内功修炼系列一反射

    “JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制 ...

  5. Java内功修炼系列一拦截器

    在动态代理中,我们知道在代理类中,执行真实对象的方法前后可以增加一些其他的逻辑,这些逻辑并不是真实对象能够实现的方法,比如一个租房的用户希望租一套公寓,但是中介所代理的这个房东并没有可以出租的公寓,那 ...

  6. Java设计模式系列-抽象工厂模式

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...

  7. Java设计模式(1)工厂模式(Factory模式)

    工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因 ...

  8. Java设计模式系列之工厂模式

    工厂模式将大量有共同接口的类实例化,工厂模式可以实现动态决定实例化哪一个类的对象,工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factory):添加某一种类型的 ...

  9. Java设计模式菜鸟系列(四)工厂方法模式建模与实现

    转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39760895 工厂方法模式(Factory Method) 工厂方法:顾名思义,就是调用工 ...

随机推荐

  1. POJ-1260-Pearls-dp+理解题意

    In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces a lot of jew ...

  2. mybatis中处理结果集映射

    单行结果集映射: 接口中方法返回值定义为Map类型,sql语句的resultType属性设置为map即可.这种情况默认把列名作为key,列中的值作为value. 也就是说用map<Strirng ...

  3. c# 多态实现_虚方法

    实现方法: 虚方法, 抽象类, 接口 1.虚方法 将父类的方法标记为虚方法,使用关键字virtual,这个方法可以被子类重新写一遍. 在父类的方法前面加上一个virtual,在子类的方法前面加上一个o ...

  4. selenium基础(窗口截图)

    窗口截图 目的:当脚本执行出错时对当前窗口进行截图 方法:get_screenshot_as_file() #打开百度首页,搜索“selenium",完成后进行截图,并将结果保存至D:/te ...

  5. CDH断电后 hbase出现spilt块不完整问题

    从错误看起来是regionspilt时候断电了,导致hbase master启动不起来,因为是测试环境只能删除这些region了,掉一部分数据 删除hbase下spilt块,删除zK里面的habse ...

  6. SpringCloud学习笔记《---03 Ribbon---》基础篇

  7. eclipse中启动tomcat之后,项目一直重复部署导致内存报警!!!

    项目环境:jdk1.8+tomcat8.0; 出现该问题的原因:目前还没有确定,网友有很多的说法. 但是我在部署其中一个项目时出现此情况,在同样的环境下部署另外一个项目未出现此情况. 其中的一种解决方 ...

  8. WPF 免费控件库(2)

    最近在逛园子的时候发现的园友分享或提及的WPF控件库~ (1) Bootstrap WPF Style,Bootstrap风格的WPF样式 转:http://www.cnblogs.com/tsliw ...

  9. Spring MVC(十一)--使用字符串实现重定向

    Spring MVC中有两种重定向方式: 通过返回字符串,字符串必须以redirect:开头: 通过返回ModelAndView: 重定向的时候如果需要给重定向目标方法传参数,要分字符串参数和pojo ...

  10. Linux查看温度

    step 1: centos $ sudo yum install lm_sensors ubuntu $ sudo apt-get install lm_sensors step2$ sudo se ...