工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

PS:在设计模式中,“实现一个接口”泛指实现某个超类型(可以是类或接口)的某个方法。

要点:

  • 通过子类来创建具体的对象。客户只需要知道他们所使用的抽象类型即可。
  • 由子类决定要实例化的类是哪一个,是指在编写创建者类时,不需要知道实际创建的产品是哪一个。选择了使用哪个创建者子类,自然就决定了实际创建的产品是什么。
  • 对象统一由定义好的工厂方法来创建。

二、实现步骤

1、创建产品抽象类

/*** 产品抽象类*/
public abstract class Product {String name;public String getName() {return name;}
}

2、创建具体的产品,并继承产品抽象类

(1)产品A1

/*** 产品A1*/
public class ConcreteProductA1 extends Product {public ConcreteProductA1() {name = "ConcreteProductA1";}
}

(2)产品A2

/*** 产品A2*/
public class ConcreteProductA2 extends Product {public ConcreteProductA2() {name = "ConcreteProductA2";}
}

(3)产品B1

/*** 产品B1*/
public class ConcreteProductB1 extends Product {public ConcreteProductB1() {name = "ConcreteProductB1";}
}

(4)产品B2

/*** 产品B2*/
public class ConcreteProductB2 extends Product {public ConcreteProductB2() {name = "ConcreteProductB2";}
}

3、创建创建者抽象类,并定义用来创建产品的工厂方法

创建者一般为需要用到产品的类,需要的产品则通过类中的工厂方法创建。

/*** 创建者抽象类*/
public abstract class Creator {/*** 创建产品(工厂方法)*/protected abstract Product createProduct(String productType);
}

4、创建具体的创建者,并继承创建者抽象类

具体的创建者需要实现创建产品的工厂方法。

(1)创建者1

/*** 创建者1*/
public class ConcreteCreator1 extends Creator {@Overrideprotected Product createProduct(String productType) {// 由具体的创建者(子类)决定创建哪个类的对象if ("A".equals(productType)) {return new ConcreteProductA1();} else if ("B".equals(productType)) {return new ConcreteProductB1();}return null;}
}

(2)创建者2

/*** 创建者2*/
public class ConcreteCreator2 extends Creator {@Overrideprotected Product createProduct(String productType) {// 由具体的创建者(子类)决定创建哪个类的对象if ("A".equals(productType)) {return new ConcreteProductA2();} else if ("B".equals(productType)) {return new ConcreteProductB2();}return null;}
}

5、创建者通过工厂方法创建产品

public class Test {public static void main(String[] args) {// 创建者1Creator creator1 = new ConcreteCreator1();// 创建者2Creator creator2 = new ConcreteCreator2();// 通过工厂方法创建产品Product product = creator1.createProduct("A");System.out.println("创建者1创建产品A:" + product.getName());product = creator2.createProduct("A");System.out.println("创建者2创建产品A:" + product.getName());}
}

三、举个栗子

1、背景

假设你有一个披萨店,出售多种类型的披萨:芝士披萨、蛤蜊披萨、素食披萨等。由于经营有成,你打算推广自己的加盟店。

为了确保加盟店运营的质量,你希望加盟店能够采用固定的制作流程。但是由于区域的差异,每家加盟店都可能想要提供不同风味的披萨(比如纽约、芝加哥、加州),因此又必须允许加盟店能够自由地制作该区域的风味。

2、实现

披萨店子类通过实现创建披萨方法来决定要创建什么风味的披萨。

(1)创建披萨抽象类

/*** 披萨抽象类*/
public abstract class Pizza {/*** 名称*/String name;/*** 面团*/String dough;/*** 酱料*/String sauce;/*** 佐料*/ArrayList<String> toppings = new ArrayList<>();void prepare() {System.out.println("Preparing " + name);System.out.println("Tossing dough...");System.out.println("Adding souce...");System.out.println("Adding toppings: ");for (int i = 0; i < toppings.size(); i++) {System.out.println(" "+ toppings.get(i));}}/*** 烘烤*/void bake() {System.out.println("Bake for 25 minutes at 350");}/*** 切片*/void cut() {System.out.println("Cutting the pizza into diagonal slices");}/*** 装盒*/void box() {System.out.println("Place pizza in official PizzaStore box");}public String getName() {return name;}
}

(2)创建不同风味、不同类型的披萨

/*** 纽约风味的芝士披萨*/
public class NYStyleCheesePizza extends Pizza {public NYStyleCheesePizza() {name = "NY Style Sauce and Cheese Pizza";dough = "Thin Crust Dough";sauce = "Marinara Sauce";toppings.add("Grated Reggiano Cheese");}
}
/*** 纽约风味的蛤蜊披萨*/
public class NYStyleClamPizza extends Pizza {public NYStyleClamPizza() {name = "NY Style Sauce Clam Pizza";dough = "Thin Crust Dough";sauce = "Marinara Sauce";toppings.add("Fresh Clams");}
}
/*** 芝加哥风味的芝士披萨*/
public class ChicagoStyleCheesePizza extends Pizza {public ChicagoStyleCheesePizza() {name = "Chicago Style Deep Dish Cheese Pizza";dough = "Extra Thick Crust Dough";sauce = "Plum Tomato Sauce";toppings.add("Shredded Mozzarella Cheese");}void cut() {System.out.println("Cutting the pizza into square slices");}
}
/*** 芝加哥风味的蛤蜊披萨*/
public class ChicagoStyleClamPizza extends Pizza {public ChicagoStyleClamPizza() {name = "Chicago Style Clam Pizza";dough = "Extra Thick Crust Dough";sauce = "Plum Tomato Sauce";toppings.add("Frozen Clams");}void cut() {System.out.println("Cutting the pizza into square slices");}
}

(3)创建披萨店抽象类

/*** 披萨店抽象类*/
public abstract www.xingyunylpt.com class PizzaStore {/*** 订购披萨*/public Pizza www.youy2zhuce.cn orderPizza(String type) {Pizza pizza www.jujinyule.com= createPizza(type);pizza.prepare( www.shentuylgw.cn);pizza.bake(www.lanboyulezc.cn);pizza.cut( www.tengyao3zc.cn);pizza.box(www.uuedzc.cn);return pizza;}/*** 创建披萨(工厂方法)*/protected abstract Pizza createPizza(String type);
}

(4)创建不同风味的披萨店

/*** 纽约风味披萨店*/
public class NYStylePizzaStore extends     protected Pizza createPizza(String type) {Pizza pizza = null;if ("cheese".equals(type)) {pizza = new NYStyleCheesePizza(); } else if ("clam".equals(type)) {pizza = new NYStyleClamPizza();}return pizza;}
}
/*** 芝加哥风味披萨店*/
public class ChicagoStylePizzaStore extends PizzaStore {@Overrideprotected Pizza createPizza(String type) {Pizza pizza lexuancaizc.cn= null;if (www.chuancenpt.com"cheese".equals(type)) {pizza = new ChicagoStyleCheesePizza(www.yuntianyul.com ); } else if ( www.jintianxuesha.com"clam".equals(type)) {pizza = new ChicagoStyleClamPizza();}return pizza;}
}

(5)使用不同风味的披萨店订购披萨

public class Test {public static void main(String[] args) {// 纽约风味披萨店PizzaStore nyStore = new NYStylePizzaStore();// 芝加哥风味披萨店PizzaStore chicagoStore = new ChicagoStylePizzaStore();// 订购芝士披萨Pizza pizza = nyStore.orderPizza("cheese");System.out.println("Ethan ordered a " + pizza.getName() + "\n");pizza = chicagoStore.orderPizza("cheese");System.out.println("Joel ordered a " + pizza.getName() + "\n");

创建具体的产品,并继承产品抽象类相关推荐

  1. 【Groovy】自定义 Xml 生成器 BuilderSupport ( 继承 BuilderSupport 抽象类 | 在 createNode 方法中获取节点名称、节点属性、节点值信息 )

    文章目录 一.继承 BuilderSupport 抽象类 二.在 createNode 方法中获取节点名称.节点属性.节点值信息 三.完整代码示例 1.MyBuilderSupport 生成器代码 2 ...

  2. 10.java基础----继承、抽象类- 编程

    命名要求:1. 类名,接口名,枚举名,注解名使用大驼峰2. 变量名,方法名,包名均使用小驼峰3. 常量名全大写,多个单词下划线分割4. 名字要见名知意,如果不知道对应的英文,可以使用拼音代替.不可使用 ...

  3. 【设计模式】抽象工厂模式 ( 简介 | 适用场景 | 优缺点 | 产品等级结构和产品族 | 代码示例 )

    文章目录 一.抽象工厂模式简介 二.抽象工厂模式适用场景 三.抽象工厂模式优缺点 四.产品等级结构和产品族 五.抽象工厂模式代码示例 1.冰箱抽象类 2.美的冰箱实现类 3.格力冰箱实现类 4.空调抽 ...

  4. 《Java技术》第三次作业--面向对象——继承、抽象类、接口

    1.阅读下面程序,分析是否能编译通过?如果不能,说明原因.应该如何修改?程序的运行结果是什么?为什么子类的构造方法在运行之前,必须调用父 类的构造方法?能不能反过来? class Grandparen ...

  5. 设计模式---4(抽象工厂模式的概念,产品组和产品等级的概念,抽象工厂模式的实现)

    抽象工厂模式 抽象工厂模式的概念 抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的.抽象工厂模式可以向 客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品 族的产 ...

  6. 产品经理如何通过拆产品,持续提升产品能力?附案例

    产品经理要持续提升产品能力,必须进行高密度的思考.决策和实践,不断重复这个循环. 但有时需求并不多,项目也不是特别急,没有太多实践的机会,这时,最好的提升方式就是练习,通过拆解直接竞品或其他产品,去学 ...

  7. 接口类的多继承以及抽象类的单继承

    接口类的多继承以及抽象类的单继承 一.接口类(面向对象开发的思想和规范)的多继承 需求: 定义一个tiger类:会走,会游 定义一个hawk类:会走,会飞 定义一个swan类:会走,会游,会飞 (a) ...

  8. Java面向对象(继承、抽象类)

    面向对象 今日内容介绍 u 继承 u 抽象类 第1章 继承 1.1 继承的概念 在现实生活中,继承一般指的是子女继承父辈的财产.在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成 ...

  9. 深入继承之抽象类和接口综合分析及完整案列解说(一)

    首先感谢园里的一位前辈anytao.cnblogs.com ,他对面向抽象类和接口编程作出比较完善的总结.下面的总结是直接Copy他的原话. 一.相同点 ● 都不能被直接实例化,都可以通过继承实现其抽 ...

最新文章

  1. Linxu终端gcc与gcc -c的区别
  2. 【PHPWord】插入Excel对象
  3. mysql子查询为什么不走索引_解决MySQL中IN子查询会导致无法使用索引问题
  4. linux怎么命令设置网络连接,Linux网络操作命令
  5. python 导入包 作用域_Python 包、模块、函数、变量作用域
  6. 汉诺塔问题(信息学奥赛一本通-T1205)
  7. 算法萌新如何学好动态规划(一)
  8. Spring-IOC 扩展点 BeanFactoryPostProcessor及其子接口解析
  9. 软件设计师历年真题与解析分享(05——17年)
  10. 系统集成项目管理工程师题型分析及章节占分比
  11. 无法访问工作组计算机修复工具,局域网共享一键修复工具
  12. 关于无线网络的静态ip与动态ip设置
  13. 什么是T1 mapping?
  14. 年轻时欠下风流情债的十大男女明星(组图)
  15. CAD三维图形转化成二维图形的过程具体的步骤
  16. RNNoise超详细解析
  17. 帆软数据可视化:BI区域地图制作
  18. Shell基础之自定义变量
  19. Android屏幕共享及远程控制【免root】
  20. 软件测试投递简历找工作总是已读不回怎么办?

热门文章

  1. 安卓手机哪个服务器信号最强,安卓手机最强性能前十排行,第一名再逆袭第二名有争议...
  2. 适合写python的电脑_文言文的适是什么意思
  3. 3d游戏建模行业真的能一直走下去麽?兴趣爱好能否带来面包
  4. 什么是软件测试(功能、接口、性能、自动化)详解
  5. React Native 炫酷的动画库 实现任何AE动画 lottie-react-native
  6. springboot+jsp志愿者岗位报名培训系统javaweb
  7. 虚荣指标 探索性指标 4种_为什么您应该避免使用虚荣指标并衡量重要问题
  8. spring关于Aspect、Joinpoint、Advice Pointcut的区别
  9. Python之线程的同步互斥与死锁
  10. web服务器的相关配置