工厂模式

目录
  • 基本介绍

  • 简单工厂模式

  • 工厂方法模式

  • 抽象工厂模式

基本介绍

  • 工厂模式:属于创建模式的一种,仔细划分的话,工厂模式大致分为三种,简单工厂模式、工厂方法模式以及抽象工厂模式。

  • 主要作用:创建对象时避免客户端直接暴露创建逻辑(解耦),而是通过一个公共的接口去创建对象。

  • 优点:①. 扩展性好,想增加产品,只要扩展相应工厂类即可。(也是缺点)②. 屏蔽产品的具体实现细节

简单工厂模式

基于上图说的场景,我们了解所有的英雄和英雄皮肤都可以被购买,那么我们先定义一个接口让所有英雄和英雄皮肤遵循这个规则

public interface Hero {
/**
 * 成功购买英雄
 */
void buyHeroSuccess();
/**
 * 成功购买配套皮肤
 */
void buySkinSuccess();

}

那么接下来我们开始定义不同的英雄,这里我们分别选 妲己、程咬金、后羿 作为示例

/**
 * 妲己
 */
public class DaJi implements Hero {

@Override
public void buyHeroSuccess() {
System.out.println("勇士,恭喜你获得了英雄-妲己!");
}

@Override
public void buySkinSuccess() {
System.out.println("恭喜你获得了皮肤-热情桑巴");
}

}
/**
 * 程咬金
 */
public class ChengYaoJin implements Hero {

@Override
public void buyHeroSuccess() {
System.out.println("勇士,恭喜你获得了英雄-程咬金!");
}

@Override
public void buySkinSuccess() {
System.out.println("恭喜你获得了皮肤-爱与正义");
}

}
/**
 * 后羿
 */
public class HouYi implements Hero {

@Override
public void buyHeroSuccess() {
System.out.println("勇士,恭喜你获得了英雄-后羿!");
}

@Override
public void buySkinSuccess() {
System.out.println("恭喜你获得了皮肤-黄金射手座");
}

}

上面我们一下子就定义了三个英雄,下面就可以开始简单工厂的核心了-工厂

既然是工厂模式,那么生产产品的时候(即创建类),由工厂统一管理,我们通过标签去决定生产什么样的产品

/**
 * 王者荣耀工厂(商城)
 */
public class HerosFactory {

/**
 * 根据不同的标签生产不同的英雄
 */
public Hero getDifferentHero(String heroType) {
if("HouYi".equals(heroType)){
return new HouYi();
}else if("DaJi".equals(heroType)){
return new DaJi();
}else if("ChengYaoJin".equals(heroType)){
return new ChengYaoJin();
}
return null;
}

}

写完了简单工厂的工厂类,我们可以写个测试方法测试一下

/**
 * 测试方法
 */
public class TestFactory {
public static void main(String[] args) {
HerosFactory herosFactory = new HerosFactory();
Hero hero1 = herosFactory.getDifferentHero("DaJi");
hero1.buyHeroSuccess();
hero1.buySkinSuccess();
System.out.println("-----------------");
Hero hero2 = herosFactory.getDifferentHero("HouYi");
hero2.buyHeroSuccess();
hero2.buySkinSuccess();
}
}

工厂方法模式

我个人认为工厂方法模式是简单工厂模式的升级,我们先想想简单工厂模式最大的缺点是啥?

如果我想新增一个对象,那么我就需要扩展工厂类,即我需要去改工厂类的生产方法代码去增加一个标签

这么干,实际违背了 开闭原则-对外扩展开放,对内修改关闭
 
比较好的方案是什么呢?

再定义一个抽象的工厂类型的基类,让子类去实现该基类(也就是工厂与实例对象遥相呼应),可能这么说,还是有人不明白,上代码

首先英雄接口部分还是和简单工厂一致

public interface Hero {
/**
 * 成功购买英雄
 */
void buyHeroSuccess();
/**
 * 成功购买配套皮肤
 */
void buySkinSuccess();

}

接着我们是已购买三个英雄,妲己、程咬金、后羿

/**
 * 妲己
 */
public class DaJi implements Hero {

@Override
public void buyHeroSuccess() {
System.out.println("勇士,恭喜你获得了英雄-妲己!");
}

@Override
public void buySkinSuccess() {
System.out.println("恭喜你获得了皮肤-热情桑巴");
}

}
/**
 * 程咬金
 */
public class ChengYaoJin implements Hero {

@Override
public void buyHeroSuccess() {
System.out.println("勇士,恭喜你获得了英雄-程咬金!");
}

@Override
public void buySkinSuccess() {
System.out.println("恭喜你获得了皮肤-爱与正义");
}

}
/**
 * 后羿
 */
public class HouYi implements Hero {

@Override
public void buyHeroSuccess() {
System.out.println("勇士,恭喜你获得了英雄-后羿!");
}

@Override
public void buySkinSuccess() {
System.out.println("恭喜你获得了皮肤-黄金射手座");
}

}

上述代码都是和简单工厂部分一致,针对我们说的问题,我们说 定义一个抽象的工厂类型的基类

/**
 * 工厂方法模式:(王者荣耀商城)
 */
public abstract class HeroFactory {

protected abstract Hero productHero();

}

我们已经看到了,基类的抽象方法可以创建英雄,那么需要创建的子类工厂通过继承该基类就可以完成创建所需英雄的功能了

/**
 * 定义一个射手英雄工厂
 */
public class ArrowFactory extends HeroFactory{

@Override
protected Hero productHero() {
return new HouYi();
}

}
/**
 * 法师工厂
 */
public class MageFactory extends HeroFactory{

@Override
protected Hero productHero() {
return new DaJi();
}

}
/**
 * 坦克工厂
 */
public class TanksFactory extends HeroFactory{

@Override
protected Hero productHero() {
return new ChengYaoJin();
}

}

定义完三个工厂,我们再次进行测试

/**
 * 测试工厂方法模式
 */
public class TestFatcoryMethod {
public static void main(String[] args) {
Hero hero1 = new ArrowFactory().productHero();
hero1.buyHeroSuccess();
hero1.buySkinSuccess();
System.out.println("------------");
Hero hero2 = new MageFactory().productHero();
hero2.buyHeroSuccess();
hero2.buySkinSuccess();
}
}

抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态模式。(不然怎么叫抽象工厂)

其次抽象工厂是指当有多个抽象角色,使用一种工厂模式。抽象工厂可以向提供一个接口,使客户端在不指定产品的具体情况下,创建多个产品族中的对象。一个抽象工厂类,可以派生多个具体工厂类,每个具体的工厂类可以创建多个产品的实例。

工厂方法模式 是对 一个产品类型进行构建,而抽象工厂则针对的 是 多个产品类型的构建。
 
下面我们用代码去演绎抽象工厂模式:

之前说过王者荣耀商城中,可以买英雄和皮肤。按照面向对象的思想我们可以将英雄 和 皮肤 单独抽取,成为最顶层的接口。那么会有下面的代码:

//英雄的顶层接口
public interface Hero {

void haveHero();

}

定义完第一个抽象角色,也就是英雄的顶层接口,接下来我们定义具体的实现

/**
 * 妲己
 */
public class DaJiHero implements Hero {

@Override
public void haveHero() {
System.out.println("勇士,恭喜你已获得-妲己");
}

}
/**
 * 程咬金
 */
public class ChengYaoJinHero implements Hero {

@Override
public void haveHero() {
System.out.println("勇士,恭喜你已获得-程咬金");
}

}
/**
 * 后羿
 */
public class HouYiHero implements Hero {

@Override
public void haveHero() {
System.out.println("勇士,恭喜你获得了英雄-后羿");
}

}

我们知道英雄还有皮肤,所以我们定义第二个抽象角色,即皮肤的顶层接口

/**
 * 皮肤
 */
public interface Skin {

void haveSkin();

}

接着定义皮肤接口的实现类

/**
 * 妲己皮肤
 */
public class DaJiSkin implements Skin{

@Override
public void haveSkin() {
System.out.println("恭喜你获得了皮肤-热情桑巴");
}

}
/**
 * 程咬金皮肤
 */
public class ChengYaoJinSkin implements Skin {

@Override
public void haveSkin() {
System.out.println("恭喜你获得了皮肤-爱与正义");
}

}
/**
 * 后羿皮肤
 */
public class HouYiSkin implements Skin{

@Override
public void haveSkin() {
System.out.println("恭喜你获得了皮肤-黄金射手座");
}

}

根据上面的概念,我们定义完了2个抽象角色,那么还需定义一个抽象工厂。可能你会问为什么要定义一个抽象工厂,因为上面的概念也说到了定义抽象工厂的目的就是为了派生具体的工厂类(也就是让子类去实现)。这个抽象工厂类加上abstract 关键字后,又该如何去写内部的逻辑,我想这一块才是最需要思考和解决的问题。

/**
 * 商品工厂(顶层多态接口 )
 */
public interface MarketFactory {

}
/**
 * 英雄抽象工厂
 */
public abstract class HeroAbStractFactory implements MarketFactory {

public abstract Hero getHero(String heroType);

}
/**
 * 皮肤抽象工厂
 */
public abstract class SkinAbStractFactory implements MarketFactory {

public abstract Skin getSkin(String skinType);

}

定义完抽象工厂,我们实现两个工厂

/**
 * 英雄工厂
 */
public class HeroFactory extends HeroAbStractFactory {

@Override
public Hero getHero(String heroType) {
if("HouYi".equals(heroType)){
return new HouYiHero();
}else if("DaJi".equals(heroType)){
return new DaJiHero();
}else if("ChengYaoJin".equals(heroType)){
return new ChengYaoJinHero();
}
return null;
}

}
/**
 * 皮肤工厂
 */
public class SkinFactory extends SkinAbStractFactory {

@Override
public Skin getSkin(String skinType) {
if("HouYi".equals(skinType)){
return new HouYiSkin();
}else if("DaJi".equals(skinType)){
return new DaJiSkin();
}else if("ChengYaoJin".equals(skinType)){
return new ChengYaoJinSkin();
}
return null;
}

}

那么,我们已经定义完具体的实例工厂,一个是英雄工厂,一个是皮肤工厂,现在可以定义一个统一管理类管理这两个工厂

/**
 * 工厂(商城)
 */
public class FactoryProduct {

public static MarketFactory getFactoryByType(String factoryType){
if("HeroFactory".equals(factoryType)){
return new HeroFactory();
}else if("SkinFactory".equals(factoryType)){
return new SkinFactory();
}
return null;
}

}

最后我们开始测试

/**
 * 工厂测试
 */
public class TestFactory {
public static void main(String[] args) {
HeroFactory heroFactory = (HeroFactory) FactoryProduct.getFactoryByType("HeroFactory");
Hero hero = heroFactory.getHero("ChengYaoJin");
hero.haveHero();
SkinFactory skinFactory = (SkinFactory) FactoryProduct.getFactoryByType("SkinFactory");
Skin skin = skinFactory.getSkin("ChengYaoJin");
skin.haveSkin();
}
}
(0)

相关推荐

  • 【设计模式】工厂方法模式(Factory Method)

    工厂方法模式(Factory Method) 工厂方法模式分为三种: 1.普通工厂模式 就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建.首先看下关系图:举例如下:(我们举一个发送邮件和短信 ...

  • 创建型设计模式--工厂模式、抽象工厂模式

    一.小案例分析 1.功能需求: 实现一个发送信息的功能,要便于扩展与维护. (1)发送信息的工具有很多,比如短信.微信.邮件.QQ等. (2)选择某个工具进行信息发送. 2.小菜鸡去实现: (1)定义 ...

  • 装饰模式

    大家好,我叫小赵,现任职藏剑山庄高级铸剑师,今天抽空跟大家唠唠嗑,希望能赚几个点击,赚几个关注. 我们山庄每天都会出很多货,每把武器打造出来之后,会进行包装,因为大众化的口味总是需要各种各样的点缀,因 ...

  • 如何学习23种设计模式及其思想?

    感觉设计模式是看着简单 ,但是一用就不会,23种设计模式,学的人头大,相信大家都是这样的 设计模式在程序员的面试中会被考到,通常是介绍其原理并说出优缺点.或者对比几个比较相似的模式的异同点.在笔试中可 ...

  • 设计模式----------工厂(Factory)模式

    作用 实现了创建者和调用者分离. 工厂模式核心/本质: 实例化对象不在使用new,而是用工厂方法代替. 将选择实现类,创建对象统一管理和控制,从而实现调用者和我们实现类解耦 工厂模式详细分类 1.简单 ...

  • 常见的设计模式及应用场景

    一.单例模式 单例模式是一种常用的软件设计模式,在应用这个模式时,单例对象的类必须保证只有一个实例存在,整个系统只能使用一个对象实例. 优点:不会频繁地创建和销毁对象,浪费系统资源. 使用场景:IO ...

  • 【设计模式】(四)抽象工厂模式(Abstract Factory Pattern)

    【设计模式】(四)抽象工厂模式(Abstract Factory Pattern)

  • 无废话设计模式(1)--简单工厂、工厂方法、抽象工厂

    0-前言 简单工厂.工厂方法.抽象工厂都是创建型的设计模式,三个设计模式都是工厂的变种,不复杂,下面我们来快速学习这三种: 1-简单工厂模式 太简单,UML图就不画了,直接上代码: //------- ...

  • 【中国的植物工厂模式】未来的城市周边种菜...

    [中国的植物工厂模式]未来的城市周边种菜模式可能是这样的,植物工厂根据城市需求来种菜,告别对天气.对阳光.对土壤的依赖,一年四季都可以种出各种蔬菜.1.种植方式是模块化种植,数字化管理:2.种植的工厂 ...

  • 敖丙所在的电商公司都是怎么用工厂模式的

    前言 不知道随着大家工作年限的增长,有没有一种危机感,害怕自己的技术深度开始没有提升,所以经常会去看一点框架的源码,或者报一些网课去提升自己. 最近我有一个老东家的同事跟我聊起来这个问题,说最近刚换公 ...

  • 【6/25】使用简单工厂模式(Simple Factory Pattern)改写Page基类

    这是<小游戏从0到1设计模式重构>系列内容第6篇,所有源码及资料在"程序员LIYI"公号回复"小游戏从0到1"获取. 工厂模式有三个姐妹:简单工厂模 ...

  • 【8/25】使用抽象工厂模式(Abstract Factory Pattern) 封装页面对象的创建过程

    这是<小游戏从0到1设计模式重构>系列内容第8篇,所有源码及资料在"程序员LIYI"公号回复"小游戏从0到1"获取. 看完了三姐妹中的大姐.二姐,最 ...

  • PHP设计模式之简单工厂模式

    PHP设计模式之简单工厂模式 先从简单工厂入门,不管是面试还是被他人面试,在问到设计模式的时候,大多数人都会提到工厂模式.毫无疑问,工厂相关的几种模式在设计模式中是最出名的也是应用比较广泛的一种模式. ...

  • PHP设计模式之抽象工厂模式

    PHP设计模式之抽象工厂模式 工厂模式系列中的重头戏来了,没错,那正是传闻中的抽象工厂模式.初次听到这个名字的时候你有什么感觉?反正我是感觉这货应该是非常高大上的,毕竟包含着"抽象" ...

  • [PHP小课堂]PHP设计模式之简单工厂模式

    PHP设计模式之工厂方法模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • [PHP小课堂]PHP设计模式之抽象工厂模式

    [PHP小课堂]PHP设计模式之抽象工厂模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 一篇带你读懂工厂模式

    工厂模式 简单工厂模式 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行 主要解决:主要解决接口选择的问题. 何时使用:我们明确地计划不同条件下创建 ...

  • 海信电视怎么进入工厂模式开启ADB调试?详细教程!|海信电视如何打开ADB调试

    作者:ZNDS资讯 来源: ZNDS资讯 2018-07-11 16:24阅读( 14649) ADB调试是电脑与设备(Android系统)进行通信的通用命令工具,在智能电视.智能投影.智能机顶盒的日 ...