从披萨店的案例引入工厂模式

披萨的种类很多(比如 GreekPizza、CheesePizza 等)

  • 披萨制作完成后需要进行cut(切片工作),box(包装工作)
  • 完成披萨店的功能

一、简单工厂模式

1、基本介绍

简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。定义了一个创建对象的工厂类,由这个工厂类来封装实例化对象的代码。

在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。

属于创建型模式。

2、代码实现

设计方案:   定义一个可以实例化 Pizaa 对象的工厂类,封装创建对象的代码。

Pizza接口

public interface Pizza {/*** 披萨切片*/void cut();/*** 披萨包装*/void box();
}

奶酪披萨

public class CheesePizza implements Pizza {public void cut() {System.out.println("奶酪披萨切片中");}public void box() {System.out.println("奶酪披萨打包中");}
}

希腊披萨

public class GreekPizza implements Pizza {public void cut() {System.out.println("希腊披萨切片中");}public void box() {System.out.println("希腊披萨打包中");}
}

创建披萨实例的工厂

public class PizzaFactory {public static Pizza getPizza(String type) {if(type.equalsIgnoreCase("CheesePizza")){return new CheesePizza();}else if(type.equalsIgnoreCase("GreekPizza")){return new GreekPizza();}else {return null;}}}

测试

public class Client {public static void main(String[] args) {Pizza cheesePizza = PizzaFactory.getPizza("CheesePizza");cheesePizza.cut();cheesePizza.box();Pizza greekPizza = PizzaFactory.getPizza("GreekPizza");greekPizza.cut();greekPizza.box();}
}

结果

奶酪披萨切片中
奶酪披萨打包中
希腊披萨切片中
希腊披萨打包中

二、工厂方法模式

看一个新的需求,客户在点披萨时,可以点不同口味的披萨,比如北京的奶酪 pizza、北京的胡椒 pizza 或者是伦敦的奶酪 pizza、伦敦的胡椒  pizza。

思路 1

使用简单工厂模式,创建不同的简单工厂类,比如 BJPizzaSimpleFactory,LDPizzaSimpleFactory等等。从当前这个案例来说,也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好。

思路 2

使用工厂方法模式

1、基本介绍

工厂方法模式:定义一个创建对象的抽象方法,由子类工厂决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。

2、代码实现

披萨类Pizza

public interface Pizza {/*** 披萨切片*/void cut();/*** 披萨包装*/void box();
}

四种披萨

public class BJChessPizza implements Pizza{public void cut() {System.out.println("北京奶酪披萨切片中");}public void box() {System.out.println("北京奶酪披萨打包中");}
}
public class BJPepperPizza implements Pizza{public void cut() {System.out.println("北京胡椒披萨切片中");}public void box() {System.out.println("北京胡椒披萨打包中");}
}
public class LDChessPizza implements Pizza{public void cut() {System.out.println("伦敦奶酪披萨切片中");}public void box() {System.out.println("伦敦奶酪披萨打包中");}
}
public class LDPepperPizza implements Pizza{public void cut() {System.out.println("伦敦胡椒披萨切片中");}public void box() {System.out.println("伦敦胡椒披萨打包中");}
}

Pizza抽象工厂

public abstract class PizzaFactory {public abstract Pizza getPizza(String type);}

北京披萨工厂,伦敦披萨工厂

public class BJPizzaFactory extends PizzaFactory {@Overridepublic Pizza getPizza(String type) {if(type.equalsIgnoreCase("chess")){return new BJChessPizza();}else if(type.equalsIgnoreCase("pepper")){return new BJPepperPizza();}else {return null;}}
}
public class LDPizzaFactory extends PizzaFactory {@Overridepublic Pizza getPizza(String type) {if(type.equals("chess")){return new LDChessPizza();}else if(type.equals("pepper")){return new LDPepperPizza();}else {return null;}}
}

测试

public class Client {public static void main(String[] args) {//北京披萨工厂BJPizzaFactory bjPizzaFactory = new BJPizzaFactory();Pizza bjChessPizza = bjPizzaFactory.getPizza("chess");bjChessPizza.cut();bjChessPizza.box();Pizza bjPepperPizza = bjPizzaFactory.getPizza("pepper");bjPepperPizza.cut();bjPepperPizza.box();//伦敦披萨工厂LDPizzaFactory ldPizzaFactory = new LDPizzaFactory();Pizza ldChessPizza = ldPizzaFactory.getPizza("chess");ldChessPizza.cut();ldChessPizza.box();Pizza ldPepperPizza = ldPizzaFactory.getPizza("pepper");ldPepperPizza.cut();ldPepperPizza.box();}
}

结果

北京奶酪披萨切片中
北京奶酪披萨打包中
北京胡椒披萨切片中
北京胡椒披萨打包中
伦敦奶酪披萨切片中
伦敦奶酪披萨打包中
伦敦胡椒披萨切片中
伦敦胡椒披萨打包中

三、抽象工厂模式

新需求:有的人喜欢吃肯德基的披萨,有的人喜欢吃麦当劳的披萨

1、基本介绍

抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类

2、代码实现

披萨接口

public interface Pizza {/*** 披萨切片*/void cut();/*** 披萨包装*/void box();
}

商店A披萨,商店B披萨接口

public interface ShopAPizza extends Pizza {
}
public interface ShopBPizza extends Pizza {
}

商店A披萨的实现类

public class ShopABJChessPizza implements ShopAPizza{public void cut() {System.out.println("商店A北京奶酪披萨切片中");}public void box() {System.out.println("商店A北京奶酪披萨打包中");}
}
public class ShopALDChessPizza implements ShopAPizza{public void cut() {System.out.println("商店A伦敦奶酪披萨切片中");}public void box() {System.out.println("商店A伦敦奶酪披萨打包中");}
}

商店B披萨的实现类

public class ShopBBJChessPizza implements ShopBPizza{public void cut() {System.out.println("商店B北京胡椒披萨切片中");}public void box() {System.out.println("商店B北京胡椒披萨打包中");}}
public class ShopBLDChessPizza implements ShopBPizza{public void cut() {System.out.println("商店B伦敦胡椒披萨切片中");}public void box() {System.out.println("商店B伦敦胡椒披萨打包中");}}

披萨工厂抽象类

public abstract class PizzaFactory {public abstract Pizza getBJChessPizza(String type);public abstract Pizza getLDChessPizza(String type);
}

商店A,B的工厂类

public class ShopAPizzaFactory extends PizzaFactory {@Overridepublic Pizza getBJChessPizza(String type) {return new ShopABJChessPizza();}@Overridepublic Pizza getLDChessPizza(String type) {return new ShopALDChessPizza();}
}
public class ShopBPizzaFactory extends PizzaFactory {@Overridepublic Pizza getBJChessPizza(String type) {return new ShopBBJChessPizza();}@Overridepublic Pizza getLDChessPizza(String type) {return new ShopBLDChessPizza();}
}

四、JDK中的工厂模式源码案例

比如说日历类Calendar就用到了简单工厂模式

我们一般这样使用

public class Test {public static void main(String[] args) {Calendar cal = Calendar.getInstance();System.out.println("年:" + cal.get(Calendar.YEAR));System.out.println("月:" + (cal.get(Calendar.MONTH) + 1));System.out.println("日:" + cal.get(Calendar.DAY_OF_MONTH));System.out.println("时:" + cal.get(Calendar.HOUR_OF_DAY));System.out.println("分:" + cal.get(Calendar.MINUTE));System.out.println("秒:" + cal.get(Calendar.SECOND));}
}

具体源码:就用到了简单工厂模式

    /*** Gets a calendar using the default time zone and locale. The* <code>Calendar</code> returned is based on the current time* in the default time zone with the default* {@link Locale.Category#FORMAT FORMAT} locale.** @return a Calendar.*/public static Calendar getInstance(){return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));}
    private static Calendar createCalendar(TimeZone zone,Locale aLocale)
//根据 TimeZone zone, Locale aLocale创建对应的实例{CalendarProvider provider =LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();if (provider != null) {try {return provider.getInstance(zone, aLocale);} catch (IllegalArgumentException iae) {// fall back to the default instantiation}}Calendar cal = null;if (aLocale.hasExtensions()) {String caltype = aLocale.getUnicodeLocaleType("ca");if (caltype != null) {switch (caltype) {case "buddhist":cal = new BuddhistCalendar(zone, aLocale);break;case "japanese":cal = new JapaneseImperialCalendar(zone, aLocale);break;case "gregory":cal = new GregorianCalendar(zone, aLocale);break;}}}if (cal == null) {// If no known calendar type is explicitly specified,// perform the traditional way to create a Calendar:// create a BuddhistCalendar for th_TH locale,// a JapaneseImperialCalendar for ja_JP_JP locale, or// a GregorianCalendar for any other locales.// NOTE: The language, country and variant strings are interned.if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {cal = new BuddhistCalendar(zone, aLocale);} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"&& aLocale.getCountry() == "JP") {cal = new JapaneseImperialCalendar(zone, aLocale);} else {cal = new GregorianCalendar(zone, aLocale);}}return cal;}

五、工厂模式小结

1、工厂模式的意义

将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。

在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式

2、三种工厂模式   (简单工厂模式、工厂方法模式、抽象工厂模式)

个人觉得这个区别在于产品,如果产品单一,最合适用工厂模式,但是如果有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的。

再来看看工厂方法模式与抽象工厂模式对比:

工厂方法模式

抽象工厂模式

针对的是一个产品等级结构 针对的是面向多个产品等级结构
一个抽象产品类 多个抽象产品类
可以派生出多个具体产品类 每个抽象产品类可以派生出多个具体产品类
一个抽象工厂类,可以派生出多个具体工厂类 一个抽象工厂类,可以派生出多个具体工厂类
每个具体工厂类只能创建一个具体产品类的实例 每个具体工厂类可以创建多个具体产品类的实例

参考文章:(1条消息) 抽象工厂模式-与-工厂方法模式区别_wyxhd2008的博客-CSDN博客

尚硅谷设计模式学习(四)工厂模式相关推荐

  1. 设计模式 - 学习笔记 - 工厂模式Factory Pattern

    设计模式 - 学习笔记 - 工厂模式Factory Pattern 1. 简单工厂 1.1 应用场景 1.2 UML 1.3 优劣分析 好处 缺点 1.4 代码示例 抽象产品 AbstractProd ...

  2. Java设计模式学习之工厂模式

    简单工厂模式 我直接上代码代码里有很详细的注解 //简单工厂模式 是由一个工厂对象决定创建出哪种产品 class Factory1 {publicstatic void main(String[] a ...

  3. 设计模式学习之工厂模式(附demo)

    介绍 工厂模式(Factory Pattern) 是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客户端暴 ...

  4. 设计模式学习总结——工厂模式

    在我们平常创建对象的时候,都是通过关键字 new 来实现的,例: Class A = new A() . 在一些情况下,要创建的对象需要一系列复杂的初始化操作,比如查配置文件.查数据库表.初始化成员对 ...

  5. Java设计模式学习02——工厂模式

    工厂模式 工厂模式主要是为创建对象提供接口,将创建对象的过程隔离起来,实现了创建者与调用者的分离,提高了程序的灵活性.  核心本质: 实例化对象,用工厂方法代替new操作. 将选择实现类.创建对象统一 ...

  6. 尚硅谷设计模式笔记-装饰者模式

    文章目录 一.需求 二.装饰者方法 三.装饰者模式的JDK应用 笔记来源: 尚硅谷 一.需求 星巴克咖啡订单项目(咖啡馆) : 咖啡种类/单品咖啡: Espresso(意大利浓咖啡). ShortBl ...

  7. 设计模式学习2 工厂模式

    工厂模式其实就是简单模式的升级版本, 简单模式将界面与业务逻辑区分开,但是如果不停的增加计算器的运算方式,简单模式中的工厂Factory 中判断的业务逻辑会变非常复杂,这不符合封装的原则. 所以在此之 ...

  8. 尚硅谷设计模式学习(1)---[设计模式七大原则]

  9. 尚硅谷设计模式学习(2)---[UML类图]

最新文章

  1. 443 ERROR [main] client.ConnectionManager$HConnectionImplementation: Can‘t get connection to ZooKeep
  2. web服务器采用的是什么协议,webservice中采用协议Http,它是指什么意思
  3. SAP C4C,CRM和S4HANA的Saved Query使用介绍
  4. wxpython使用实例_wxPython中文教程入门实例
  5. delphi基本语法
  6. 开源的类似于Apache ab的压力测试命令行工具SuperBenchmarker
  7. js使用hover事件做一个“个人中心”的浮动层
  8. php 函数有命名空间吗_解析 ThinkPHP 的命名空间
  9. java caller_js中的caller和callee属性
  10. 百度SEO站群音乐聚合源码/自动采集(在线可播放)
  11. Windows Server 2008 \u0026 2012在GCE上正式商用了
  12. ref:LDAP入门
  13. spring boot设置项目名称
  14. 手机号空号检测的几点建议
  15. php加skplayer,WordPress免插件集成ckplayer播放器
  16. html+移动端图片点击放大,移动端点击图片放大特效PhotoSwipe.js插件实现
  17. 智能POS删除文件和数据库操作步骤
  18. 算法竞赛宝典 递归算法 地盘划分
  19. eclipse新建java项目报错 jrt-fs.jar
  20. HDU 1870 愚人节的礼物

热门文章

  1. 学习php技术最快需要多久,学php最快要多久 学习路线
  2. 计算机房防凝露保温材料,数据中心机房墙面如何做保温?
  3. 任务车间调度问题的混合整数规划模型
  4. 水箱建模最小二乘法_lammps软件学习基础操作建模
  5. “Chain of Thought Reasoning“ 和 “Chain Prompts“ 是什么
  6. JBoss Seam框架
  7. 代码实现pe文件图标替换
  8. 燃料电池聚合物电解质膜高低温退化性能测试中的TEC半导体制冷温控解决方案
  9. win10s上不了网,网卡代码驱动异常代码56。
  10. 问题:UltraISO:这个软件有问题,它制作的iso文件会造成无法正确识别。用PowerISO吧...