【design pattern】工厂方法模式和抽象工厂模式

前言

设计模式分为三大类:

创建型模式:工厂方法模式抽象工厂模式、单例模式、建造者模式、原型模式;

结构型模式:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式;

行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式;

简单工厂

首先要明确的是,简单工厂模式不属于23种设计模式,它引入了创建者的概念,将实例化的代码从应用代码中抽离,在工厂类的静态方法中只处理被创建的对象,如果业

务需要变更则需要在工厂类中添加具体的实现类,因此维护性较差。以"工厂创建咖啡"为例说明,如下:

1. 物品标识类Coffee和已有的类

package com.oxygen.bean;/*** * 咖啡则作为一种抽象概念:拿铁、美式咖啡、卡布奇诺等均为咖啡家族的一种产品* @author Oxygen**/
public abstract class Coffee {public abstract String desc(); //获取coffee名称

}class Americano extends Coffee { // 美式咖啡
@Overridepublic String desc() {return "美式咖啡";}}class Cappuccino extends Coffee { //卡布奇诺
@Overridepublic String desc() {return "卡布奇诺";}}class Latte extends Coffee { //拿铁
@Overridepublic String desc() {return "拿铁";}}
View Code

2. 简单工厂

package com.oxygen.bean;/*** 创建材料的工厂类* @author Oxygen *    @date 2018年10月16日*/
public class SimpleFactory {/*** * @param type 材料类型* @return*/public static Coffee createInstance(String type) {if ("Americano".equals(type)) {return new Americano();} else if ("Cappuccino".equals(type)) {return new Cappuccino();} else if ("Latte".equals(type)) {return new Latte();} else {throw new RuntimeException("type[" + type + "]类型不可识别,没有匹配到可实例化的对象!");}}public static void main(String[] args) {System.out.println(SimpleFactory.createInstance("Americano").desc());System.out.println(SimpleFactory.createInstance("Cappuccino").desc());System.out.println(SimpleFactory.createInstance("Latte").desc());}
}
View Code

3. 输出结果

美式咖啡
卡布奇诺
拿铁

工厂方法

 工厂方法模式其定义了一个创建对象的接口,由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到了子类,也就是说一个工厂只能生成特定的Coffee

1. 工厂类

package com.oxygen.bean;/*** Coffee工厂* @author Oxygen *    @date 2018年10月16日*/
public abstract interface CoffeeFactory {public abstract Coffee[] createCoffee();public static void main(String[] args) {CoffeeFactory chinaCoffeeFactory = new ChinaCoffeeFactory();Coffee[] chinaCoffees = chinaCoffeeFactory.createCoffee();System.out.print("中国咖啡工厂可以生产的咖啡有:");print(chinaCoffees);CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();Coffee[] americaCoffees = americaCoffeeFactory.createCoffee();System.out.print("美国咖啡工厂可以生产的咖啡有:");print(americaCoffees);}public static void print(Coffee[] c) {for (Coffee coffee : c) {System.out.print(coffee.desc() + " ");}System.out.println();}
}class ChinaCoffeeFactory implements CoffeeFactory { //中国咖啡工厂
@Overridepublic Coffee[] createCoffee() {return new Coffee[] { new Cappuccino(), new Latte() };}}class AmericaCoffeeFactory implements CoffeeFactory { //美国咖啡工厂
@Overridepublic Coffee[] createCoffee() {return new Coffee[] { new Americano(), new Latte() };}}
View Code

2. 输出结果

中国咖啡工厂可以生产的咖啡有:卡布奇诺 拿铁 
美国咖啡工厂可以生产的咖啡有:美式咖啡 拿铁 

抽象工厂

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类,在上述的场景上继续延伸:咖啡工厂做大做强,引入了新的饮品种类:茶、 碳酸饮

料。中国工厂只能制造咖啡和茶,美国工厂只能制造咖啡和碳酸饮料,如果继续使用上述工厂方法方式,除去对应的产品实体类还需要新增2个抽象工厂(茶制造

工厂、碳酸饮料制造工厂),4个具体工厂实现。

随着产品的增多,会导致类爆炸,这显然是不能接受的。所以这里引出一个概念产品家族,在此例子中,不同的饮品就组成我们的饮品家族, 饮品家族开始承担

创建者的责任,负责制造不同的产品。如下:

package com.oxygen.bean;public interface AbstractDrinksFactory {Coffee createCoffee(); //制造咖啡
Tea createTea(); //制造茶
Sodas createSodas();//制造碳酸饮料
}/*** 中国饮品工厂:制造咖啡与茶*/
class ChinaDrinksFactory implements AbstractDrinksFactory {@Overridepublic Coffee createCoffee() {return new Latte();}@Overridepublic Tea createTea() {return new MilkTea();}@Overridepublic Sodas createSodas() {// TODO Auto-generated method stubreturn null;}
}/*** 美国饮品制造工厂:制造咖啡和碳酸饮料*/
class AmericaDrinksFactory implements AbstractDrinksFactory {@Overridepublic Coffee createCoffee() {// TODO Auto-generated method stubreturn new Latte();}@Overridepublic Tea createTea() {// TODO Auto-generated method stubreturn null;}@Overridepublic Sodas createSodas() {// TODO Auto-generated method stubreturn new CocaCola();}}
View Code

总结

工厂模式可以帮助我们针对抽象接口编程,而不是针对具体类编程,在不同的场景下按具体情况来

1. 简单工厂:不能算是真正意义上的设计模式,但可以将客户程序从具体类解耦;

2. 工厂方法:使用继承,把对象的创建委托给子类,由子类来实现创建方法,可以看作是抽象工厂模式中只有单一产品的情况;

3. 抽象工厂:使对象的创建被实现在工厂接口所暴露出来的方法中;

转载于:https://www.cnblogs.com/oxygenG/p/9797254.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux中使用随机数

(1)单纯使用rand重复调用n次,就会得到一个0-RAND_MAX之间的伪随机数,如果需要调整范围,可以得到随机数序列后再进行计算。(2)单纯使用rand来得到伪随机数序列有缺陷,每次执行程序得到的伪随机序列是同一个序列,没法得到…

mysql 异地备份工具_异地备份简单实现(mysql)

该脚本只适用于MYISAM引擎,如果需要适用于innodb,请修改备份命令即可。#!/bin/bash#该脚本只能用来备份myisam引擎数据库#author:vaedit#date:2017/9/18#备份过程function beifen(){BACKDIRdate "%Y-%m-%d-%H"mkdir /backup/$BACKD…

python管理数据库设计_Pycharm+Django+Python+MySQL开发 后台管理数据库

Django框架十分简单易用,适合搭建个人博客网站。网上有很多教程,大多是关于命令行操作Django,这里分享一些用最新工具进行Django开发过程,主要是PyCharm太强大,不用有点可惜。第一次写技术开发类的博文,可能…

你鼓舞了我是世界杯主题曲吗_选择方法和鼓舞人心的网站列表

你鼓舞了我是世界杯主题曲吗by Kristoffer Andreasen通过克里斯托弗安德烈森 选择方法和鼓舞人心的网站列表 (The pick and choose approach and a list of inspirational websites) In the past couple of years I have created quite a few websites. In the beginning, I h…

共享程序集GAC

原文标题: 原文地址:https://www.cnblogs.com/1996V/p/9037603.html 共享程序集GAC 我上面说了这么多有关CLR加载程序集的细节和规则,事实上,类似于mscorlib.dll、System.dll这样的FCL类库被引用的如此频繁,它已经是我…

弹簧触摸开关原理图_10年老电工经验之谈:常见的开关电源那些事儿

随着电控系统中对控制回路安全性要求提高,控制回路的工作电压是越来越趋于直流低压化。由此,控制回路内各种使用直流电源的传感器、中小微型直流继电器等电器装置是日益增多。也正因如此,电控系统内不同品牌的开关电源也相应地多了起来。因牵…

erlang mysql连接超时_Erlang数据库-(一)Erlang与Mysql的连接

下载:http://download.csdn.net/detail/hjhjava/7088277把该文件的东西全部编译好,然后根据下面的解释就可以操作Mysql的。很简单~-record(row,{a1 0, a20}).%% 第一个参数是该链接的名字(根据它来操作Mysql),第二参数是本机号(ip地址)%% &a…

SQL SERVER 中 GO 的用法2

具体不废话了&#xff0c;请看下文详解。 12345678910use db_CSharpgoselect *,备注casewhen Grade>90 then 成绩优秀when Grade<90 and Grade>80 then 成绩良好when Grade<80 and Grade>70 then 成绩及格else 不及格endfrom tb_Grade如果只是执行一条语句&…

js中判断值不等于undefined

文章&#xff1a;JS 中判断空值 undefined 和 null转载于:https://www.cnblogs.com/Tpf386/p/9804496.html

reddit_我在3天内疯狂地审查了Reddit上的50个投资组合,从中学到了什么。

redditI’ve always enjoyed critiquing applicants’ portfolios at the design studio where I work. And I also often ask for feedback on my own designs on Reddit’s webdev subreddit.我一直都很喜欢在我工作的设计工作室里评估申请人的作品集。 我也经常在Reddit的we…

【BZOJ1001】[BeiJing2006]狼抓兔子

挺简单一个题&#xff0c;最小割模板 我的感觉就是可能建图的时候会比较麻烦吧&#xff0c;毕竟三个方向。 #include <cctype> #include <climits> #include <cstdio> #include <cstring> #include <iostream>#define debug(x) std::cout <&l…

管理活动目录域服务实训_管理学院学生党支部开展实践教育基地服务活动

红星E校有态度 有温度 可关注为进一步加强党的建设&#xff0c;深化管理学院学生党支部与实践基地的互动性&#xff0c;2020年9月11至12日&#xff0c;管理学院学生党支部协助白鹤村村委实践基地完成第七次人口普查相关工作&#xff0c;共计6名预备党员参与。工作开始前的培训会…

mysql 汉编码 的选_peewee连接mysql汉语言数据编码_mysql

peewee连接mysql中文数据编码系统是win7 x64python 2.7.6的site.py里面编码设定为 utf-8py文件首行指定 #coding:utf-8mysql 5.5.38安装时指定代码为utf-8peewee的连接数据库代码为&#xff1a;db MySQLDatabase(host 127.0.0.1, user root, passwd 1, database mz, chars…

配置windows失败,还原更新,请勿关机

最近给同事装系统&#xff0c;偶尔会出现如下问题&#xff1a; 如果是这种情况&#xff0c;只能耐心等待了&#xff0c;因为关机也没用&#xff01; 转载于:https://www.cnblogs.com/lijy/p/5327844.html

使用Express和MongoDB构建简单的CRUD应用程序

by Zell Liew由Zell Liew 使用Express和MongoDB构建简单的CRUD应用程序 (Building a Simple CRUD Application with Express and MongoDB) For a long time, I didn’t dare venture into back end development. I felt intimidated because of my lack of an academic backgr…

python元类的使用_python中元类用法实例

本文实例讲述了python中元类用法&#xff0c;分享给大家供大家参考。具体方法分析如下&#xff1a;1.元类(metaclass)是用来创建类的类2.type(object):返回一个对象的类型&#xff0c;与object.__class__的值相同&#xff0c;type(name,bases,dict):创建一个新的type类型&#…

使用uicollectionView时需要注意的问题

1.UICollectionView使用流水布局——UICollectionViewFlowLayout时&#xff0c;需要满足条件&#xff1a; 每个item(即cell)的大小是一样的&#xff0c;不仅是宽度&#xff0c;还有高度。这样&#xff0c;当collectionview的宽度发生变化时&#xff0c;item能将其动态填充。ite…

hiveql函数笔记(二)

1、数据查询 //提高聚合的性能 SET hive.map.aggrtrue; SELECT count(*),avg(salary) FROM employees; //木匾不允许在一个查询语句中使用多于一个的函数&#xff08;DISTINCT。。。&#xff09;表达式 SELECT count(DISTINCT symbol) FROM stocks; 表生成函数&#xff1a; exp…

jQuery 常用的方法

<!DOCTYPE html><html lang"en"><head> <meta charset"utf-8"/> <title>品牌列表案例</title> <script src"js/jquery-2.1.1.min.js" rel"script"></script> <script…

swift 从手机选照片_19元起!定制专属手机壳!还可免费打印照片...

△剧透&#xff1a;文末有福利现在的年轻人体内涌动的都是追求有趣有特色的灵魂希望自己是这条gai最独一无二的仔撞衫撞包撞手机壳可以说是当代年轻人三大时尚忌讳尤其是手机壳极为重要毕竟换壳≈换机只需要几十元买新壳就可以拥有换新机般的仪式感不过作为手机壳老手都知道在某…