工厂模式是一种创建型模式,它提供了一种新的创建对象的方式,一般情况下我们都习惯用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. dockerfile自动创建docker镜像

    特点:类似于ansible 剧本,大小几kb 而,手动做的镜像,要几百M,甚至上G ,传输不方便 dockerfile 支持自定义容器的初始命令 dockerfile只要组成部分: 基础镜像信息 FR ...

  2. import socket模块

    编写两个小脚本实现聊天功能0.1: 脚本一,服务器端:server.py import socket # 调用模块 sk = socket.socket() # 创建socket addess = ( ...

  3. springboot-配置多数据源(AOP实现)(HikariCP + MybatisPlus + mysql + SqlServer)

    场景: springboot项目,默认使用HikariCP连接池 + MybatisPlus持久层框架 + mysql数据库等一套流程,现需求需去第三方sqlserver数据库拉取数据,直连数据库,不 ...

  4. Java中循环体的初步了解以及另一种随机数的获取方法

    Math中的相关操作 随机数 Java中除了可以直接导入Random类,获取随机数,还可以通过本身自带的Math方法去获取随机数.Math.random()可以产生随机小数,区间范围为[0.0,1.0 ...

  5. 通过key_len分析联合索引的使用

    The key_len column indicates the length of the key that MySQL decided to use. The length is NULL if ...

  6. POJ - 2774~POJ - 3415 后缀数组求解公共字串问题

    POJ - 2774: 题意: 求解A,B串的最长公共字串 (摘自罗穗骞的国家集训队论文): 算法分析: 字符串的任何一个子串都是这个字符串的某个后缀的前缀. 求 A 和 B 的最长 公共子串等价于求 ...

  7. 数据类中引用virtual

    public class City { [Key] public int CityID { set; get; } [Display(Name = "城市名称")] [Requir ...

  8. C# 16进制与字符串、字节数组之间的转换(串口通讯中)

    1.c#中如何将十进制数的字符串转化成十六进制数的字符串//十进制转二进制 Console.WriteLine("十进制166的二进制表示: "+Convert.ToString( ...

  9. Python调用DLL动态链接库——ctypes使用

    最近要使用python调用C++编译生成的DLL动态链接库,因此学习了一下ctypes库的基本使用. ctypes是一个用于Python的外部函数库,它提供C兼容的数据类型,并允许在DLL或共享库中调 ...

  10. css实现截取文本

    .ellipsis{ max-width: 260px; // 自定义 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; ...