抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)
在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实例化这个对象,好处就是客户端并不知道这个实例化的对象的实际实现,从而可以将这个对象随意替换成我们需要的不同实现
工厂方法(Factory Method)
概念:定义一个用于创建对象的接口,让子类决定实例化哪个类.它使一个类的实例化延迟到其子类
结构图:

抽象工厂(Abstract Factory)
概念: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类.
结构图:

单例模式(Singleton Pattern)
概念: 保证一个类仅有一个实例,并提供一个访问它的全局访问点
结构图:

很长一段时间我都无法理解抽象工厂和工厂方法的区别,现在我的理解是
1. 抽象工厂是提供创建一组产品类的接口的一个类(工厂),它只提供创建这个类的接口,至于具体如何创建,创建的是这个类的什么子类,这些都不是抽象工厂关心的范畴,换句话说,我们在很多设计模式例子所看到的使用具体工厂继承抽象工厂来生成产品的例子,只是抽象工厂的其中一种实现,也就是说抽象工厂仅仅是定义了一组生产产品的接口,一个没有实现的抽象工厂仅仅定义了这样一组接口,是无法使用的.而生产的实现是需要依赖其他设计模式的,例如工厂方法,原型模式.按照我的理解,单纯的谈论抽象工厂,它应该只包含下面这样的定义
public abstract class ABFactory {
public abstract Product1 createProduct1();
public abstract Product2 createProduct2();
}
2. 在定义中我们看到AbstractFactory拥有具体的ConcreteFactory实现,这个实现的方式其实就是工厂方法,他将具体生产product的方法实现延迟到了子类
3. 为了生产产品,首先我们要获取工厂,而由于工厂的无状态性,往往会将工厂作为单例使用,所以我们创建和获取工厂的方法使用单例来实现
下面是一个例子
抽象工厂类
package factory; import product.Body;
import product.Head; import java.util.HashMap;
import java.util.Map; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-7-31
* Time: 下午11:32
* To change this template use File | Settings | File Templates.
*/
public abstract class ModuleFactory { // 对于抽象工厂而言,由于instance有多种实现
// 所以此处使用一个instanceMap存储所有的Factory实现
// 如果只有一个instance,那么多线程环境下我们将只能使用过一种类型的Factory
public static String CAT_MODULE_FACTORY = "cat_module_factory";
public static String DOG_MODULE_FACTORY = "dog_module_factory";
// 单例工厂列表
private static Map<String, ModuleFactory> instanceMap = new HashMap<String, ModuleFactory>();
static {
// 舍弃延迟加载,直接减给所有factory注册进Map里
// 好处是不要每增加一个具体工厂就去修改createFactory里的判断你条件
// 只需要在这个注册代码块里将新的工厂注册进去,而这个注册代码块可以
// 写在别的类或者配置文件里来实现,这样就达成了新增工厂和创建工厂解耦
instanceMap.put(CAT_MODULE_FACTORY, new CatModuleFactory());
instanceMap.put(DOG_MODULE_FACTORY, new DogModuleFactory());
} private static Object lockObj = new Object(); // 动态返回单例的工厂
public static ModuleFactory createFactory(String factoryType) {
if (factoryType == null)
throw new RuntimeException("Param factoryType cannot be null"); // 延迟实例化各不同该类型的工厂
// 舍弃延迟加载技术,则可以省去if条件判断
// if (instanceMap.get(factoryType) == null) {
// synchronized (lockObj) {
// if (instanceMap.get(factoryType) == null) {
// if (factoryType.equals(CAT_MODULE_FACTORY)) {
// instanceMap.put(CAT_MODULE_FACTORY, new CatModuleFactory());
// } else if (factoryType.equals(DOG_MODULE_FACTORY)) {
// instanceMap.put(DOG_MODULE_FACTORY, new DogModuleFactory());
// } else {
// throw new RuntimeException("FactoryType " + factoryType + " undefined");
// }
// }
// }
// } return instanceMap.get(factoryType);
} // 工厂方法
public abstract Head createHead();
public abstract Body createBody();
}
具体工厂类
package factory; import product.Body;
import product.CatBody;
import product.CatHead;
import product.Head; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-7-31
* Time: 下午11:36
* To change this template use File | Settings | File Templates.
*/
public class CatModuleFactory extends ModuleFactory {
@Override
public Head createHead() {
return new CatHead();
} @Override
public Body createBody() {
return new CatBody();
}
} package factory; import product.Body;
import product.DogBody;
import product.DogHead;
import product.Head; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-7-31
* Time: 下午11:36
* To change this template use File | Settings | File Templates.
*/
public class DogModuleFactory extends ModuleFactory {
@Override
public Head createHead() {
return new DogHead();
} @Override
public Body createBody() {
return new DogBody();
}
}
产品类
package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:24
* To change this template use File | Settings | File Templates.
*/
public abstract class Body {
public abstract void dance();
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:27
* To change this template use File | Settings | File Templates.
*/
public class CatBody extends Body {
@Override
public void dance() {
System.out.println("A caaat's body is dancing crazily!!");
}
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:27
* To change this template use File | Settings | File Templates.
*/
public class DogBody extends Body {
@Override
public void dance() {
System.out.println("A dooog's body is dancing!");
}
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:24
* To change this template use File | Settings | File Templates.
*/
public abstract class Head {
public abstract void eat();
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:29
* To change this template use File | Settings | File Templates.
*/
public class CatHead extends Head {
@Override
public void eat() {
System.out.println("A caaat's head is eating fast");
}
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:29
* To change this template use File | Settings | File Templates.
*/
public class DogHead extends Head {
@Override
public void eat() {
System.out.println("A dooog's head is eating");
}
}
测试类
import factory.CatModuleFactory;
import factory.DogModuleFactory;
import factory.ModuleFactory;
import product.Body;
import product.Head; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:00
* To change this template use File | Settings | File Templates.
*/
public class Test { // 通过工厂解耦方法内animal实现
// 这个方法就是多态代码的实现
public static void act(ModuleFactory factory) {
Head head = factory.createHead();
Body body = factory.createBody();
head.eat();
body.dance();
} public static void main(String[] args) {
ModuleFactory factory = ModuleFactory.createFactory(ModuleFactory.CAT_MODULE_FACTORY);
act(factory);
factory = ModuleFactory.createFactory(ModuleFactory.DOG_MODULE_FACTORY);
act(factory);
}
}
输出
A caaat's head is eating fast
A caaat's body is dancing crazily!!
A dooog's head is eating
A dooog's body is dancing!
抽象工厂的优点和缺点
优点
1.分离具体类和客户端的耦合,客户端只需要根据Head和Body这种产品抽象类来编写代码,而具体实现则由具体的factory来决定(如act()方法)
2.易于替换产品系列,要使用不同的产品系列,只需要替换具体的factory即可(如act()方法)
3.可以保持产品系列的一致性,不会出现CatHead和DogBody这样的组合(至少基于工厂方法的抽象工厂是如此)
缺点
抽象工厂对新产品的支持度较差(无论是基于工厂方法还是基于原型),加入新加入了一个Foot的product,则需要在抽象工厂中加入抽象方法createFoot()并在所有的具体工厂中实现这个createFoot()方法.
工厂方法的优点和缺点
很大程度上工厂方法的优点和缺点与抽象工厂是类似的,因为工厂方法是抽象工厂的实现之一
优点
用户只需要针对抽象的产品类或接口进行编码,而不必关注具体实现类,达到与产品类解耦和多态的目的
缺点
工厂方法是一个产品-创建器的平行结构,每增加一个产品则需要增加一个创建器,应对变化的能力较差
单例模式的优点和缺点
优点
1.使用单例可以节省系统资源
2.可以严格控制对唯一实例的访问
3. GoF中文版写的优点全都没看懂....
缺点: 没看懂
抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)的更多相关文章
- Swift 实现单例模式Singleton pattern的三种方法
转自:点击打开链接 From my short experience with Swift there are three approaches to implement the Singleton ...
- 面向对象设计——抽象工厂(Abstract Factory)模式
定义 提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类.抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道或关心实际产出的具体产品是什么.这样一来,客户就能从具体的产 ...
- JAVA设计模式(01):创建型-工厂模式【工厂方法模式】(Factory Method)
简单工厂模式尽管简单,但存在一个非常严重的问题.当系统中须要引入新产品时,因为静态工厂方法通过所传入參数的不同来创建不同的产品,这必然要改动工厂类的源码,将违背"开闭原则".怎样实 ...
- python 设计模式之工厂模式 Factory Pattern (简单工厂模式,工厂方法模式,抽象工厂模式)
十一回了趟老家,十一前工作一大堆忙成了狗,十一回来后又积累了一大堆又 忙成了狗,今天刚好抽了一点空开始写工厂方法模式 我看了<Head First 设计模式>P109--P133 这25页 ...
- 5、抽象工厂 abstract factory 将关联组件组成产品 创建型模式
趁热打铁,紧跟着上一节的工厂方法模式.这一节介绍一下抽象工厂模式,以及分析俩个模式的不同 1.何为抽象模式? 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他 ...
- 设计模式——抽象工厂(Abstract Factory)
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类. ——DP UML类图 模式说明 抽象工厂与工厂方法在定义上最明显的区别是“创建一系列相关或相互依赖对象的接口”,由此可以看出抽象工 ...
- 设计模式——工厂方法(Factory Method)
定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. ——DP UML类图 模式说明 抽象业务基类 实际业务类的公共基类,也是工厂要创建的所有对象的父类,这部分 ...
- Spring 通过工厂方法(Factory Method)来配置bean
Spring 通过工厂方法(Factory Method)来配置bean 在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. ...
- 设计模式四: 抽象工厂(Abstract Factory)
简介 抽象工厂模式是创建型模式的一种, 与工厂方法不同的是抽象工厂针对的是生产一组相关的产品, 即一个产品族. 抽象工厂使用工厂方法模式来生产单一产品, 单一产品的具体实现分别属于不同的产品族. 抽象 ...
随机推荐
- 浅谈jvm
1 .说起jvm,很多人感觉jvm离我们开发实际很远.但是,我们开发缺每时每刻都离不开jvm. a: java源码 编译后成.class字节码文件, b:根据classpath找到这个字节码文件, c ...
- django Form 表单 总结与小实例
开头寄语: 这几天一直在看Django的form表单验证,然后想对于这几天要有个总结. 首先,先来看一下找到的一个form表单验证的流程: 验证过程 流程详解1. 函数full_clean()依次调用 ...
- 初始Winsock编程
1.套接字的创建和关闭 使用套接字之前,必须使用socket函数创建一个套接字,此函数调用成功将返回一个套接字句柄. 1 SOCKET socket( 2 int af, //用来指定套接字使用的地址 ...
- jdk与eclipse不匹配的各种问题。。。
- bzoj——2127: happiness
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 2570 Solved: 1242[Submit][Status][D ...
- Swift2.0语言教程之类的方法
Swift2.0语言教程之类的方法 Swift2.0语言的方法 方法其实就是函数,只不过它被定义在了类中.在Swift中,根据被使用的方式不同,方法分为了实例方法和类型方法两种.这两种方法的定义也和O ...
- CSS3组件化之菊花loading
<div class="juhua-loading"> <div class="jh-circle"></div> < ...
- python中%r和%s的区别
%r用rper()方法处理对象 %s用str()方法处理对象 有些情况下,两者处理的结果是一样的,比如说处理int型对象. 例一: print "I am %d years old.&quo ...
- [ 转载 ] Java基础13--equals方法
一.equals方法介绍 1.1.通过下面的例子掌握equals的用法 1 package cn.galc.test; 2 3 public class TestEquals { 4 public s ...
- Python学习笔记(一):Python基础学习
总结的内容: 1.变量的命名 2.脚本的注释 3.运算符 4.用户输入语句 一.变量的命名 1.变量用于引用在程序中可能会变化的值.它们被称为变量是因为它们可能引用存储在内存中的不同的值. 2.变量的 ...