一、先来了解一下设计模式的存在意义和到底有多少种,分为几大类?
设计模式是伟大的前人(GOF)为了提高面向对象代码的复用性,提出对接口编程而不是对实现编程,优先使用对象组合而不是继承,使用设计模式可以使得代码提高复用性,可读可理解性和可靠性。汇集前人(众多开发人员)的智慧,就像是拥有好厨艺的厨师们纷纷献出自己的总结的看家本领和烹饪技巧,以激励后人在从事此行业的时候能规范到行业的某些错误低效行为,能够使得从业者够驾轻就熟的在行业里发挥自己的创造力,而不是走一些不必要的弯路。
设计模式有23种,分为3大类。分为创建型模式,结构型模式,行为型模式。
创建型模式 |
|
|||||||||||||||
结构型模式 |
|
|||||||||||||||
行为型模式 |
|
二、简单工厂模式
先了解简单工厂模式,再了解工厂模式之后再到抽象工厂模式,因为简单的工厂模式虽然不是23种模式之一,却是一种编码习惯,用代码来看看:
/**
* @author Grance
*/
public class Glass {
public String bottle(){
return "装水的function";
}
}
/**
* @author Grance
*三个子类继承Glass类
*/
public class TreeGlass extends Glass {
}
/**
* @author Grance
*/
public class HotGlass extends Glass {
}
/**
* @author Grance
*/
public class WaterGlass extends Glass {
}
/**
* @author Grance
*创建一个GlassFactory 可以通过指定type来创建类
*/
public class GlassFactory {
public GlassFactory() {
}
public Glass createGlass(String type) {
switch (type) {
case "water":
return new WaterGlass();
case "hot":
return new HotGlass();
case "tree":
return new TreeGlass();
default:
return null;
}
}
public static void main(String[] args) {
//给多种选择
GlassFactory glassFactory = new GlassFactory();
Glass water = glassFactory.createGlass("water");
//选择后使用 输出装水的function
System.out.println(water.bottle());
}
以上是简单工厂模式,通过将创建对象交给工厂类去做,需要什么类型就传什么字段。
三、什么是工厂模式?
工厂模式的特点是定义一个创建的接口,但是由子类决定实例化的类是哪一个。工厂方法让类把实例化推给子类,封装了对象的创建过程。怎么表达能够清楚呢,场景:一个GlassStore类里面需要获取一个彩色的杯子,如果将创建不同色彩的杯子的逻辑放在TestGlass类里面一违反了“开放闭合原则”,二来TestGlass类就相当于客户,不是每一个客户都需要知道创建杯子的过程,这种细节应该是需要被封装起来的。所以有了ColorGlassFactory 专门用来创建杯子的实例,这时候获取一个杯子就只需要用工厂来创建,而当需要大量扩张的时候,GlassStory作为提供加工的地方,而各个连锁店(BeijinGlassStory、ShenzhenGlasStory)可以根据需求设计不同长宽高,圆方棱的杯子。
/**
* @author Grance
*/
public class GlassStory {
//本来是这样的 但是有了工厂之后生意火爆准备开连锁点,总店要作为榜样
public void getGlass(){
GlassFactory factory = new GlassFactory();
Glass water = factory.createGlass("water");
//获取到对象后对其后续加工
water.draw();
water.bottle();
water.pacage();
water.send();
}
}
public abstract class GlassStory {
//总店变身成为抽象类,不管杯子哪里来,只关注加工部分,
// 将子类需要哪种杯子交给子类
public Glass fabricat(String type){
Glass water = createGlass(type);
//获取到对象后对其后续加工
water.draw();
water.bottle();
water.pacage();
water.send();
return water;
}
public abstract Glass createGlass(String type);
}
/**
* @author Grance
*/
public class WaterGlass implements Glass {
@Override
public String draw() {
return "WaterGlass~draw";
}
@Override
public String bottle() {
return "WaterGlass~bottle";
}
@Override
public String packaged() {
return "WaterGlass~packaged";
}
@Override
public String send() {
return "WaterGlass~send";
}
}
/**
* @author Grance
*/
public class TreeGlass implements Glass{
@Override
public String draw() {
return "draw a duck on it";
}
@Override
public String bottle() {
return "TreeGlass-bottle";
}
@Override
public String packaged() {
return "TreeGlass-packaged";
}
@Override
public String send() {
return "TreeGlass-packaged";
}
}
/**
* @author Grance
*/
public class BeijinGlassStory extends GlassStory {
@Override
public Glass createGlass(String type) {
switch (type){
case "water":
return new WaterGlass();
case "tree":
return new TreeGlass();
case "hot":
return new HotGlass();
default:
break;
}
return null;
}
}
/**
* @author Grance
*/
public class ShenzhenGlasStory extends GlassStory {
@Override
public Glass createGlass(String type) {
switch (type) {
case "water":
return new WaterGlass();
case "tree":
return new TreeGlass();
case "hot":
return new HotGlass();
default:
break;
}
return null;
}
}
public class NiceCustomer {
public static void main(String[] args) {
//在北京分店买一个水杯
goBeijin();
//去深圳也买了一个杯子
goShenzhen();
}
private static void goShenzhen() {
ShenzhenGlasStory szStory = new ShenzhenGlasStory();
Glass tree = szStory.createGlass("tree");
System.out.println(tree.draw());
System.out.println(tree.send());
}
private static void goBeijin() {
BeijinGlassStory beiStory = new BeijinGlassStory();
Glass water = beiStory.createGlass("water");
//WaterGlass~draw
System.out.println(water.draw());
}
}
工厂模式有个很重要的点:所谓的“实现一个接口”并不一定表示“写一个类,并利用implement关键词来实现某个Java的接口”。
“实现一个接口”泛指“实现某个超类型(可以是接口或类)的某个方法”
想到我们常用的Logger,一起来看看
1、平常使用是这样的
public class TestServlet extends AbstractServlet {
private static final Logger logger = LoggerFactory.getLogger(TestServlet.class);
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2、LoggerFactory被final所修饰,里面有个getLogger(Class clazz)方法,从StaticLoggerBinder.getSingleton().getLoggerFactory()获取ILoggerFactory。
public static Logger getLogger(Class clazz) {
return getLogger(clazz.getName());
}
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
//ILoggerFactory实例在编译时与这个类绑定
public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
performInitialization();
}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITIALIZATION:
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITIALIZATION:
return NOP_FALLBACK_FACTORY;
case FAILED_INITIALIZATION:
throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
case ONGOING_INITIALIZATION:
// support re-entrant behavior.
// See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
return TEMP_FACTORY;
}
throw new IllegalStateException("Unreachable code");
}
3、ILoggerFactory 是接口,里面有public Logger getLogger(String name)
public interface ILoggerFactory {
public Logger getLogger(String name);
}
4、 Log4jLoggerFactory 实现 ILoggerFactory接口,并重写了getLogger方法在里面添加了Logger slf4jLogger = null;用于创建Logger 对象
public class Log4jLoggerFactory implements ILoggerFactory {
public Logger getLogger(String name) {
Logger slf4jLogger = null;
// protect against concurrent access of loggerMap
synchronized (this) {
slf4jLogger = (Logger) loggerMap.get(name);
if (slf4jLogger == null) {
org.apache.log4j.Logger log4jLogger;
if(name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) {
log4jLogger = LogManager.getRootLogger();
} else {
log4jLogger = LogManager.getLogger(name);
}
slf4jLogger = new Log4jLoggerAdapter(log4jLogger);
loggerMap.put(name, slf4jLogger);
}
}
return slf4jLogger;
}
}
其他的先放一边,主要是想表达通过工厂来实例化对象,创建对象的时候是使用接口的引用,而不是直接的实例化对象。