迁移仓库
17
.gitignore
vendored
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
/.idea/*
|
||||||
|
/.idea/
|
||||||
|
.idea/*
|
||||||
|
.idea/
|
||||||
|
out/*
|
||||||
|
out/
|
||||||
|
*.iml
|
||||||
|
tags
|
||||||
|
_book
|
||||||
|
node_modules
|
||||||
|
gradle/
|
||||||
|
build/
|
||||||
|
.gradle
|
||||||
|
bin/*
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings
|
34
README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# 设计模式
|
||||||
|
|
||||||
|
设计模式是我们必须要掌握的一项技能 <br>
|
||||||
|
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、
|
||||||
|
让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式
|
||||||
|
是软件工程的基石脉络,如同大厦的结构一样。
|
||||||
|
|
||||||
|
|
||||||
|
## 六大设计原则
|
||||||
|
|
||||||
|
* [单一职责原理](principle#1单一职责原理-)
|
||||||
|
* [里氏替换原则](principle#1里氏替换原则)
|
||||||
|
* [依赖倒置原则](principle#3依赖倒置原则)
|
||||||
|
* [接口隔离原则](principle#4接口隔离原则)
|
||||||
|
* [迪米特法则](principle#5迪米特法则)
|
||||||
|
* [开闭原则](principle#6开闭原则)
|
||||||
|
|
||||||
|
## 23种设计模式
|
||||||
|
|
||||||
|
* 创建型模式:
|
||||||
|
[简单工厂模式](simpleFactory)、[抽象工厂模式](com.zeekling.abstractFactory)、[单例模式](simgleton) 、[建造者模式](Builder)、[原型模式](com.zeekling.Prototype);
|
||||||
|
* 结构型模式:
|
||||||
|
[适配器模式](com.zeekling.adapter) 、[桥接模式](bridge)、[代理模式](gproxy)、[组合模式](gcomposite)、[外观模式](gfacade) 、[装饰模式](gdecorate)、[享元模式](gflyweight);
|
||||||
|
* 行为型模式:
|
||||||
|
[责任链模式](com.zeekling.handler)、[迭代子模式](giterator) 、[备忘录模式](gmemento) 、[命令模式](gcommand)、[状态模式](gstate) 、[观察者模式](gobserver) 、[策略模式](gstrategy) 、[模板模式](gtemplate) 、[访问者模式](gvisitor) 、[中介者模式](gmediator) 、[解释器模式](ginterpreter);
|
||||||
|
|
||||||
|
|
||||||
|
## 存在的问题
|
||||||
|
在学习设计模式时,发现了一个问题:自己这样看别人例子,没有实践,对设计模式的理解不是特别容易。不过我尽我可能理解。
|
||||||
|
|
||||||
|
## 感悟
|
||||||
|
|
||||||
|
最近发现一味的在网上google看博客是不行的,这样自己对知识很难有一个整体的把握,觉得google看博客和看书结合起来是一个很不错的选择。
|
||||||
|
|
14
build.gradle
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
group 'com.zeekling'
|
||||||
|
version '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
apply plugin: 'java'
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||||
|
}
|
172
gradlew
vendored
Executable file
@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java com.zeekling.command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' com.zeekling.command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java com.zeekling.command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
84
gradlew.bat
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' com.zeekling.command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get com.zeekling.command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the com.zeekling.command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the com.zeekling.command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
BIN
pics/abstractFactory.jpg
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
pics/bridge.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
pics/builder.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
pics/classAdapter.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
pics/command.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
pics/composite.jpg
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
pics/decorator.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
pics/facade.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
pics/flyweight1.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
pics/flyweight2.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
pics/handler.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
pics/head.jpg
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
pics/iterator.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
pics/memento.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
pics/objectAdapter.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
pics/prototype.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
pics/proxy.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
pics/simpleFactory.png
Normal file
After Width: | Height: | Size: 749 KiB |
BIN
pics/simplePrototype.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
66
principle/readme.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
## 设计模式的六大原则
|
||||||
|
### 1、单一职责原理
|
||||||
|
不要存在多余一个类变更的原因。通俗的说,集一个类只负责一项职责。总结一句话:不能代码量少,把牛头马嘴一起往一个类塞。基本和unix的编程思想一致。
|
||||||
|
优点:
|
||||||
|
- 减低系统复杂度,结构清晰.
|
||||||
|
- 提高代码的可读性
|
||||||
|
- 提高系统的可维护性
|
||||||
|
|
||||||
|
### 2、里氏替换原则
|
||||||
|
定义:所有引用基类(父类)的地方必须能透明地使用其子类的对象。
|
||||||
|
|
||||||
|
简单来讲就是,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使
|
||||||
|
用的是一个子类对象的话,那么它不一定能够使用基类对象。
|
||||||
|
|
||||||
|
* 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
|
||||||
|
* 子类中可以增加自己特有的方法。
|
||||||
|
* 当子类的方法重载父类方法时,方法的前置条件()即方法的行参)要比父类方法输入的参数更加宽松。
|
||||||
|
* 当子类的方法实现父类的抽象方法时,方法的后置条件()即方法的返回值)要比父类更严格。
|
||||||
|
|
||||||
|
采用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。
|
||||||
|
在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美。
|
||||||
|
|
||||||
|
尽量不要重写父类已经实现了的方法,可以用接口等其他方法绕过。
|
||||||
|
|
||||||
|
### 3、依赖倒置原则
|
||||||
|
定义:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。
|
||||||
|
|
||||||
|
依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合。在项目中使
|
||||||
|
用,我们只要遵循以下几个规则就可以.
|
||||||
|
|
||||||
|
- 每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备。
|
||||||
|
- 变量的表名类型尽量是接口或者抽象类。
|
||||||
|
- 任何类都不应该从具体类派生。
|
||||||
|
- 尽量不要覆写基类的方法。
|
||||||
|
- 结合里氏替换原则使用
|
||||||
|
|
||||||
|
高层模块不应该依赖底层模块,二者应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
|
||||||
|
总结:读用抽象的接口来描述相同的动作,降低实现这个动作的人和物之间的耦合度。
|
||||||
|
|
||||||
|
### 4、接口隔离原则
|
||||||
|
客户端不应该依赖他不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
|
||||||
|
根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即
|
||||||
|
可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。
|
||||||
|
看到这里好像接口隔离原则与单一职责原则是相同的。其实接口隔离原则与单一职责原则的审视角度是不相同的,单一职责原则要
|
||||||
|
求的是类和接口职责单一,注重的是职责,这是业务逻辑上的划分,而接口隔离原则要求接口的方法尽量少。
|
||||||
|
接口隔离原则是对接口进行规范约束,其包含的以下4层含义:
|
||||||
|
|
||||||
|
- 接口要尽量少。
|
||||||
|
- 接口要高内聚。
|
||||||
|
- 定制服务。
|
||||||
|
- 接口设计师有限度的。
|
||||||
|
|
||||||
|
在使用接口隔离原则时,我们需要注意控制接口的粒度,接口不能太小,如果太小会导致系统中接口泛滥,不利于维护;接口也不
|
||||||
|
能太大,太大的接口将违背接口隔离原则,灵活性较差,使用起来很不方便。一般而言,接口中仅包含为某一类用户定制的方法即
|
||||||
|
可,不应该强迫客户依赖于那些它们不用的方法。
|
||||||
|
|
||||||
|
接口隔离原则是对接口的定义,同时也是对类的定义,接口和类尽量使用原子接口或原子类来组装。但是,这个原子该怎么划分是
|
||||||
|
设计模式中的一大难题,在实践中可以根据以下几个规则来衡量.
|
||||||
|
|
||||||
|
### 5、迪米特法则
|
||||||
|
迪米特法则又叫最小知道原则。通俗的来讲,就是一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类来说,无论逻辑多么复杂,
|
||||||
|
都尽量将>逻辑封装在类的内部,对外除了提供的public方法,不对外泄漏任何信息。
|
||||||
|
总结:
|
||||||
|
|
||||||
|
### 6、开闭原则
|
||||||
|
尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
|
2
settings.gradle
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
rootProject.name = 'design-pattern'
|
||||||
|
|
39
src/README.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# 设计模式
|
||||||
|
|
||||||
|
设计模式是我们必须要掌握的一项技能 <br>
|
||||||
|
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、
|
||||||
|
让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式
|
||||||
|
是软件工程的基石脉络,如同大厦的结构一样。
|
||||||
|
|
||||||
|
|
||||||
|
## 六大设计原则
|
||||||
|
|
||||||
|
* [单一职责原理](principle#1单一职责原理-) <br>
|
||||||
|
* [里氏替换原则](principle#1里氏替换原则) <br>
|
||||||
|
* [依赖倒置原则](principle#3依赖倒置原则) <br>
|
||||||
|
* [接口隔离原则](principle#4接口隔离原则) <br>
|
||||||
|
* [迪米特法则](principle#5迪米特法则) <br>
|
||||||
|
* [开闭原则](principle#6开闭原则) <br>
|
||||||
|
|
||||||
|
## 23种设计模式
|
||||||
|
|
||||||
|
* 创建型模式:
|
||||||
|
[简单工厂模式](main/java/simpleFactory)、[抽象工厂模式](main/java/abstractFactory)、[单例模式](main/java/simgleton) 、[建造者模式](main/java/Builder)、[原型模式](main/java/Prototype); <br>
|
||||||
|
* 结构型模式:
|
||||||
|
[适配器模式](main/java/adapter) 、[桥接模式](main/java/bridge)、[代理模式](gproxy)、[组合模式](gcomposite)、[外观模式](gfacade) 、[装饰模式](gdecorate)、[享元模式](gflyweight);<br>
|
||||||
|
* 行为型模式:
|
||||||
|
[责任链模式](main/java/handler)、[迭代子模式](giterator) 、[备忘录模式](gmemento) 、[命令模式](gcommand)、[状态模式](gstate) 、[观察者模式](gobserver) 、[策略模式](gstrategy) 、[模板模式](gtemplate) 、[访问者模式](gvisitor) 、[中介者模式](gmediator) 、[解释器模式](ginterpreter);
|
||||||
|
|
||||||
|
## 相关github项目
|
||||||
|
|
||||||
|
[最近在看设计模式时在github上面看到了一个写的不错的有关设计模式的项目就fork了过了打算仔细看看](https://github.com/lzh-fork/DPModel)
|
||||||
|
## 存在的问题
|
||||||
|
在学习设计模式时,发现了一个问题:自己这样看别人例子,没有实践,对设计模式的理解不是特别容易。不过我尽我可能理解。
|
||||||
|
|
||||||
|
## 感悟
|
||||||
|
|
||||||
|
最近发现一味的在网上google看博客是不行的,这样自己对知识很难有一个整体的把握,觉得google看博客和看书结合起来是一个很不错的选择。
|
||||||
|
|
||||||
|
<img src="http://zeekling.mynatapp.cc/gogs/zeek/designPattern/raw/master/pics/head.jpg">
|
||||||
|
|
||||||
|
----
|
12
src/main/java/com/zeekling/abstractFactory/AbstractFactory.java
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
package com.zeekling.abstractFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @apiNote 抽象工厂模式
|
||||||
|
* @author zeekling
|
||||||
|
* @version 1.0
|
||||||
|
* @since 2019-12-04
|
||||||
|
*/
|
||||||
|
public interface AbstractFactory {
|
||||||
|
void america();
|
||||||
|
void chinese();
|
||||||
|
}
|
11
src/main/java/com/zeekling/abstractFactory/Board.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
package com.zeekling.abstractFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创造主板
|
||||||
|
*/
|
||||||
|
public interface Board {
|
||||||
|
|
||||||
|
void americaBoard();
|
||||||
|
|
||||||
|
void chineseBoard();
|
||||||
|
}
|
11
src/main/java/com/zeekling/abstractFactory/Display.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
package com.zeekling.abstractFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建显示屏
|
||||||
|
*/
|
||||||
|
public interface Display {
|
||||||
|
|
||||||
|
void americaDisplay();
|
||||||
|
|
||||||
|
void chineseDisplay();
|
||||||
|
}
|
7
src/main/java/com/zeekling/abstractFactory/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# 抽象工厂模式
|
||||||
|
## 简介
|
||||||
|
抽象工厂模式为创建一组对象提供了一种解决方案。与简单工厂模式,抽象工厂模式中的具体工厂模式不只是创建一种产品,他负责创建一组产品。
|
||||||
|
## 使用场景
|
||||||
|
为创建一组对象提供了一种解决方案
|
||||||
|
## UML类图
|
||||||
|
![抽象工厂模式](https://git.zeekling.cn/java/designPattern/raw/master/pics/abstractFactory.jpg)
|
18
src/main/java/com/zeekling/abstractFactory/impl/BoardImpl.java
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
package com.zeekling.abstractFactory.impl;
|
||||||
|
|
||||||
|
import com.zeekling.abstractFactory.Board;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 16-6-10.
|
||||||
|
*/
|
||||||
|
public class BoardImpl implements Board {
|
||||||
|
@Override
|
||||||
|
public void americaBoard() {
|
||||||
|
System.out.println("美国产主板");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void chineseBoard() {
|
||||||
|
System.out.println("中国产主板");
|
||||||
|
}
|
||||||
|
}
|
18
src/main/java/com/zeekling/abstractFactory/impl/DisplayImpl.java
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
package com.zeekling.abstractFactory.impl;
|
||||||
|
|
||||||
|
import com.zeekling.abstractFactory.Display;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DisplayImpl implements Display {
|
||||||
|
@Override
|
||||||
|
public void americaDisplay() {
|
||||||
|
System.out.println("美国产显示屏");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void chineseDisplay() {
|
||||||
|
System.out.println("中国产显示屏");
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/com/zeekling/abstractFactory/impl/FactoryImpl.java
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
package com.zeekling.abstractFactory.impl;
|
||||||
|
|
||||||
|
import com.zeekling.abstractFactory.AbstractFactory;
|
||||||
|
import com.zeekling.abstractFactory.Display;
|
||||||
|
import com.zeekling.abstractFactory.Board;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 16-6-10.
|
||||||
|
*/
|
||||||
|
public class FactoryImpl implements AbstractFactory {
|
||||||
|
private Display button = null;
|
||||||
|
private Board panel = null;
|
||||||
|
|
||||||
|
public FactoryImpl() {
|
||||||
|
try {
|
||||||
|
button = DisplayImpl.class.newInstance();
|
||||||
|
panel = BoardImpl.class.newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void america() {
|
||||||
|
panel.americaBoard();
|
||||||
|
button.americaDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void chinese() {
|
||||||
|
panel.chineseBoard();
|
||||||
|
button.chineseDisplay();
|
||||||
|
}
|
||||||
|
}
|
10
src/main/java/com/zeekling/adapter/Alibaba.java
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
package com.zeekling.adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
*/
|
||||||
|
public class Alibaba {
|
||||||
|
public void mayun(){
|
||||||
|
System.out.println("Alibaba");
|
||||||
|
}
|
||||||
|
}
|
8
src/main/java/com/zeekling/adapter/Baidu.java
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
package com.zeekling.adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
*/
|
||||||
|
public interface Baidu {
|
||||||
|
void liyanhong();
|
||||||
|
}
|
12
src/main/java/com/zeekling/adapter/BaiduImp.java
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
package com.zeekling.adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
*/
|
||||||
|
public class BaiduImp extends Alibaba implements Baidu {
|
||||||
|
@Override
|
||||||
|
public void liyanhong() {
|
||||||
|
super.mayun();
|
||||||
|
System.out.println("Baidu");
|
||||||
|
}
|
||||||
|
}
|
49
src/main/java/com/zeekling/adapter/readme.md
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
# 适配器模式
|
||||||
|
## 适配器模式有两种实现方式:
|
||||||
|
类适配器模式和对象适配器模式
|
||||||
|
* 类适配器模式:就是让适配器角色继承源角色、实现目标接口。
|
||||||
|
* 对象适配器模式:就是在目标接口的实现类中new一个源角色的对象,通过这个对象达到适配的效果。
|
||||||
|
在tomcat中有好多地方都用到了适配器模式,在平时的开发中也遇到了适配器模式。
|
||||||
|
## 类适配器模式
|
||||||
|
![类适配器模式](http://www.zeekling.cn/gogs/zeek/designPattern/raw/master/pics/classAdapter.png) <br>
|
||||||
|
在上图中可以看出,Adaptee类并没有sampleOperation2()方法,而客户端则期待这个方法。为使客户端能够
|
||||||
|
使用Adaptee类,提供一个中间环节,即类Adapter,把Adaptee的API与Target类的API衔接起来。Adapter与
|
||||||
|
Adaptee是继承关系,这决定了这个适配器模式是类的。
|
||||||
|
#### 目标(Target)角色
|
||||||
|
这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。
|
||||||
|
#### 源(Adapee)角色
|
||||||
|
现在需要适配的接口。
|
||||||
|
#### 适配器(Adaper)角色
|
||||||
|
适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
|
||||||
|
## 对象适配器
|
||||||
|
与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成为目标类的API,与类的适配器模式不同
|
||||||
|
的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。<br>
|
||||||
|
|
||||||
|
![对象适配器模式](http://www.zeekling.cn/gogs/zeek/designPattern/raw/master/pics/objectAdapter.png) <br>
|
||||||
|
|
||||||
|
从上图可以看出,Adaptee类并没有sampleOperation2()方法,而客户端则期待这个方法。为使客户端能够使用
|
||||||
|
Adaptee类,需要提供一个包装Wrapper类Adapter。这个包装类包装了一个Adaptee的实例,从而此包装类能够
|
||||||
|
把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。
|
||||||
|
## 优点
|
||||||
|
* 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
|
||||||
|
* 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
|
||||||
|
* 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适
|
||||||
|
配器类,完全符合“开闭原则”。<br>
|
||||||
|
|
||||||
|
#### 类适配器模式还具有如下优点
|
||||||
|
* 由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
|
||||||
|
|
||||||
|
#### 对象适配器模式还具有如下优点
|
||||||
|
* 一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
|
||||||
|
|
||||||
|
## 缺点
|
||||||
|
|
||||||
|
#### 类适配器模式的缺点
|
||||||
|
* 一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,
|
||||||
|
不能将一个适配者类和它的子类都适配到目标接口。
|
||||||
|
|
||||||
|
#### 对象适配器的缺点
|
||||||
|
* 与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,
|
||||||
|
就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进
|
||||||
|
行适配,实现过程较为复杂。
|
||||||
|
|
14
src/main/java/com/zeekling/adapter/test/Test.java
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
package adapter.adapter.test;
|
||||||
|
|
||||||
|
import com.zeekling.adapter.Baidu;
|
||||||
|
import com.zeekling.adapter.BaiduImp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Baidu baidu = new BaiduImp();
|
||||||
|
baidu.liyanhong();
|
||||||
|
}
|
||||||
|
}
|
8
src/main/java/com/zeekling/bridge/AbstractCar.java
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
package com.zeekling.bridge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 16-6-11.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractCar {
|
||||||
|
public abstract void run();
|
||||||
|
}
|
16
src/main/java/com/zeekling/bridge/AbstractRoad.java
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
package com.zeekling.bridge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 16-6-11.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractRoad {
|
||||||
|
private AbstractCar car = null;
|
||||||
|
public abstract void run();
|
||||||
|
public void setCar(AbstractCar car){
|
||||||
|
this.car = car;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractCar getCar() {
|
||||||
|
return car;
|
||||||
|
}
|
||||||
|
}
|
11
src/main/java/com/zeekling/bridge/Car.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
package com.zeekling.bridge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 16-6-11.
|
||||||
|
*/
|
||||||
|
public class Car extends AbstractCar {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.out.println("car");
|
||||||
|
}
|
||||||
|
}
|
13
src/main/java/com/zeekling/bridge/Street.java
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
package com.zeekling.bridge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 16-6-11.
|
||||||
|
*/
|
||||||
|
public class Street extends AbstractRoad {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
super.getCar().run();
|
||||||
|
System.out.println(super.getCar().getClass().getName()+" run on street");
|
||||||
|
}
|
||||||
|
}
|
8
src/main/java/com/zeekling/bridge/readme.md
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
# 桥接模式:
|
||||||
|
## 简介
|
||||||
|
Bridge 模式又叫做桥接模式,是构造型的设计模式之一。Bridge模式基于类的最小设计原则,通过使用
|
||||||
|
封装,聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是把抽象(abstraction)与行
|
||||||
|
为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。
|
||||||
|
## 桥接模式结构
|
||||||
|
![桥接模式结构](http://www.zeekling.cn/gogs/zeek/designPattern/raw/master/pics/bridge.jpg)
|
||||||
|
|
16
src/main/java/com/zeekling/bridge/test/Test.java
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
package bridge.bridge.test;
|
||||||
|
|
||||||
|
import com.zeekling.bridge.AbstractRoad;
|
||||||
|
import com.zeekling.bridge.Car;
|
||||||
|
import com.zeekling.bridge.Street;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 16-6-11.
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
AbstractRoad abstractRoad = new Street();
|
||||||
|
abstractRoad.setCar(new Car());
|
||||||
|
abstractRoad.run();
|
||||||
|
}
|
||||||
|
}
|
35
src/main/java/com/zeekling/builder/Ant.java
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
package com.zeekling.builder;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/28/16.
|
||||||
|
*/
|
||||||
|
public class Ant {
|
||||||
|
private String head;
|
||||||
|
private String body;
|
||||||
|
private String foot;
|
||||||
|
|
||||||
|
public String getFoot() {
|
||||||
|
return foot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFoot(String foot) {
|
||||||
|
this.foot = foot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(String body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHead() {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHead(String head) {
|
||||||
|
this.head = head;
|
||||||
|
}
|
||||||
|
}
|
15
src/main/java/com/zeekling/builder/AntBuilder.java
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
package com.zeekling.builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创造蚂蚁需要的所有步骤以及获取蚂蚁
|
||||||
|
*/
|
||||||
|
public interface AntBuilder {
|
||||||
|
|
||||||
|
void buildHead();
|
||||||
|
|
||||||
|
void buildBody();
|
||||||
|
|
||||||
|
void buildFoot();
|
||||||
|
|
||||||
|
Ant getAnt();
|
||||||
|
}
|
28
src/main/java/com/zeekling/builder/AntBuilderImp.java
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
package com.zeekling.builder;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创造蚂蚁需要的所有步骤以及获取蚂蚁
|
||||||
|
*/
|
||||||
|
public class AntBuilderImp implements AntBuilder {
|
||||||
|
private Ant ant = new Ant();
|
||||||
|
@Override
|
||||||
|
public void buildHead() {
|
||||||
|
ant.setHead("head");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildBody() {
|
||||||
|
ant.setBody("body");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildFoot() {
|
||||||
|
ant.setFoot("foot");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Ant getAnt() {
|
||||||
|
return ant;
|
||||||
|
}
|
||||||
|
}
|
25
src/main/java/com/zeekling/builder/Director.java
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
package com.zeekling.builder;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指挥创建蚂蚁
|
||||||
|
*/
|
||||||
|
public class Director {
|
||||||
|
|
||||||
|
private AntBuilder builder;
|
||||||
|
|
||||||
|
public Director(AntBuilder builder){
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照指定的顺序创建蚂蚁
|
||||||
|
* @return 创建得到的蚂蚁
|
||||||
|
*/
|
||||||
|
public Ant buildAnt(){
|
||||||
|
builder.buildHead();
|
||||||
|
builder.buildBody();
|
||||||
|
builder.buildFoot();
|
||||||
|
return builder.getAnt();
|
||||||
|
}
|
||||||
|
}
|
24
src/main/java/com/zeekling/builder/readme.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# 建造者模式
|
||||||
|
## 简介
|
||||||
|
建造者模式(com.zeekling.builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,
|
||||||
|
它提供了一种创建对象的最佳方式。
|
||||||
|
## 主要解决
|
||||||
|
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求
|
||||||
|
的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
|
||||||
|
## 建造者的结构
|
||||||
|
![建造者模式](http://www.zeekling.cn/gogs/zeek/designPattern/raw/master/pics/builder.png)
|
||||||
|
|
||||||
|
## 抽象建造者(com.zeekling.builder)角色
|
||||||
|
给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建
|
||||||
|
产品对象的是具体建造者 ConcreteBuilder角色。具体建造者类必须实现这个接口所要求的两种方法:一种是建造方法
|
||||||
|
buildPart1和 buildPart2,另一种是返还结构方法retrieveResult。一般来说,产品所包含的零件数目与建造方法的数目相符。
|
||||||
|
换言之,有多少 零件,就有多少相应的建造方法。
|
||||||
|
## 具体建造者(ConcreteBuilder)角色
|
||||||
|
担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。这个角色要完成的任务包括:
|
||||||
|
1.实现抽象建造者Builder所声明的接口,给出一步一步地完成创建产品实例的操作。2.在建造过程完成后,提供产品的实例。
|
||||||
|
## 导演者(Director)角色
|
||||||
|
担任这个角色的类调用具体建造者角色以创建产品对象。应当指出的是,导演者角色并没有产品类的具体知识,真正拥有产品
|
||||||
|
类的具体知识的是具体建造者角色。
|
||||||
|
## 产品(Product)角色
|
||||||
|
产品便是建造中的复杂对象。一般来说,一个系统中会有多于一个的产品类,而且这些产品类并不一定有共同的接口,而完全
|
||||||
|
可以是不相关联的。
|
21
src/main/java/com/zeekling/builder/test/Test.java
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
package Builder.builder.test;
|
||||||
|
|
||||||
|
|
||||||
|
import com.zeekling.builder.Ant;
|
||||||
|
import com.zeekling.builder.AntBuilder;
|
||||||
|
import com.zeekling.builder.AntBuilderImp;
|
||||||
|
import com.zeekling.builder.Director;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 建造者模式
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
AntBuilder builder = new AntBuilderImp();
|
||||||
|
Director director = new Director(builder);
|
||||||
|
System.out.println("begin build.......");
|
||||||
|
Ant ant = director.buildAnt();
|
||||||
|
System.out.println("build end");
|
||||||
|
System.out.println("head=" + ant.getHead()+",body="+ant.getBody()+",foot="+ant.getFoot());
|
||||||
|
}
|
||||||
|
}
|
11
src/main/java/com/zeekling/command/Command.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
package com.zeekling.command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 命令模式
|
||||||
|
*/
|
||||||
|
public interface Command {
|
||||||
|
|
||||||
|
void execute();
|
||||||
|
|
||||||
|
}
|
18
src/main/java/com/zeekling/command/Eat.java
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
package com.zeekling.command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 具体命令。
|
||||||
|
*/
|
||||||
|
public class Eat implements Command {
|
||||||
|
|
||||||
|
private Person person;
|
||||||
|
|
||||||
|
public Eat(Person person){
|
||||||
|
this.person = person;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
person.action("eat");
|
||||||
|
}
|
||||||
|
}
|
32
src/main/java/com/zeekling/command/Invoker.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package com.zeekling.command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 令照辉 [zeekling@163.com]
|
||||||
|
* @version 1.0
|
||||||
|
* @apiNote
|
||||||
|
* @since 2018-05-21
|
||||||
|
*/
|
||||||
|
public class Invoker {
|
||||||
|
|
||||||
|
private Command command;
|
||||||
|
|
||||||
|
public Invoker(){}
|
||||||
|
|
||||||
|
public Invoker(Command command){
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void call(){
|
||||||
|
if (command != null){
|
||||||
|
command.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Command getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommand(Command command) {
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
}
|
30
src/main/java/com/zeekling/command/Person.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package com.zeekling.command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 令照辉 [zeekling@163.com]
|
||||||
|
* @version 1.0
|
||||||
|
* @apiNote
|
||||||
|
* @since 2018-05-21
|
||||||
|
*/
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Person(){}
|
||||||
|
|
||||||
|
public Person(String name){
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void action(String action){
|
||||||
|
System.out.println(name + ":" + action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
18
src/main/java/com/zeekling/command/Sleep.java
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
package com.zeekling.command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 4/1/16.
|
||||||
|
*/
|
||||||
|
public class Sleep implements Command {
|
||||||
|
|
||||||
|
private Person person;
|
||||||
|
|
||||||
|
public Sleep(Person person){
|
||||||
|
this.person = person;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
person.action("sleep");
|
||||||
|
}
|
||||||
|
}
|
17
src/main/java/com/zeekling/command/Walk.java
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
package com.zeekling.command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 4/1/16.
|
||||||
|
*/
|
||||||
|
public class Walk implements Command {
|
||||||
|
private Person person;
|
||||||
|
|
||||||
|
public Walk(Person person) {
|
||||||
|
this.person = person;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
person.action("walk");
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/com/zeekling/command/readme.md
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
# 命令模式
|
||||||
|
又称Action模式或者Transaction模式。它属于对象的行为模式。命令模式把一个请求或者操作封装到一个对象中。命令模式
|
||||||
|
允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和撤销功能。
|
||||||
|
|
||||||
|
## 主要角色
|
||||||
|
|
||||||
|
#### 抽象命令(Command)角色
|
||||||
|
声明执行操作的接口。
|
||||||
|
#### 具体命令(ConcreteCommand)角色
|
||||||
|
将一个接收者对象绑定到一个动作上。调用接收者相应的操作,以实现Execute方法。
|
||||||
|
#### 客户端(Client)角色
|
||||||
|
创建一个命令对象并设定它的接收者。
|
||||||
|
#### 请求者(Invoker)角色
|
||||||
|
负责调用命令对象的执行请求;
|
||||||
|
#### 接收者(Receiver)角色
|
||||||
|
负责具体实施和执行一个请求相关的操作。任何一个类都可以作为一个接收者。
|
||||||
|
|
||||||
|
## 命令模式结构图
|
||||||
|
|
||||||
|
![命令模式](http://www.zeekling.cn/gogs/zeek/designPattern/raw/master/pics/command.jpg)
|
||||||
|
|
||||||
|
## 命令模式的优点
|
||||||
|
1、在命令者模式中,请求者不直接与接受者互交,既请求者不包含接受者的引用,因此彻底消除了彼此之间的耦合。
|
||||||
|
2、命令者模式满足了软件的“开-闭原则”。如果增加新的具体命令和该命令的接受者,不必修改调用者的代码,调用者就可以
|
||||||
|
直接使用新的命令对象。反之如果增加新的调用者,不必修改现有的具体命令和接受者。新增加的调用者就可以使用已有的具
|
||||||
|
体命令。
|
||||||
|
3、由于请求者的请求被封装到了具体命令中,那么就可以将具体命令保存到持久化媒介中,在需要的时候重新执行这个具体
|
||||||
|
命令。因此使用命令者模式可以记录日志。
|
||||||
|
4、使用命令者模式可以对请求者的请求进行排队,每个请求者各自对应一个具体命令,因此可以按一定的顺序执行这些命令。
|
||||||
|
## 命令模式应用场景
|
||||||
|
1、程序需要在不同的时刻指定,排列和执行请求。
|
||||||
|
2、程序需要提供撤销操作 。
|
||||||
|
3、程序需要支持宏操作 。
|
||||||
|
|
23
src/main/java/com/zeekling/command/test/Test.java
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
package com.zeekling.command.test;
|
||||||
|
|
||||||
|
|
||||||
|
import com.zeekling.command.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Person person = new Person("令照辉");
|
||||||
|
Invoker invoker = new Invoker();
|
||||||
|
Command command = new Eat(person);
|
||||||
|
invoker.setCommand(command);
|
||||||
|
invoker.call();
|
||||||
|
command = new Walk(person);
|
||||||
|
invoker.setCommand(command);
|
||||||
|
invoker.call();
|
||||||
|
command = new Sleep(person);
|
||||||
|
invoker.setCommand(command);
|
||||||
|
invoker.call();
|
||||||
|
}
|
||||||
|
}
|
26
src/main/java/com/zeekling/composite/Component.java
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
package com.zeekling.composite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
* 组合模式。
|
||||||
|
*/
|
||||||
|
public abstract class Component {
|
||||||
|
|
||||||
|
String msg;
|
||||||
|
|
||||||
|
public Component(String msg){
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Component component){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(Component component){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void display(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/com/zeekling/composite/Composite.java
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
package com.zeekling.composite;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
*/
|
||||||
|
public class Composite extends Component {
|
||||||
|
private ArrayList<Component> components = new ArrayList<>();
|
||||||
|
public Composite(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(Component component) {
|
||||||
|
super.add(component);
|
||||||
|
components.add(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Component component) {
|
||||||
|
super.remove(component);
|
||||||
|
if(components.contains(component)){
|
||||||
|
components.remove(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void display() {
|
||||||
|
super.display();
|
||||||
|
for (Component c:components) {
|
||||||
|
System.out.println(c.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/main/java/com/zeekling/composite/Part.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
package com.zeekling.composite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
*/
|
||||||
|
public class Part extends Component {
|
||||||
|
|
||||||
|
public Part(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/com/zeekling/composite/readme.md
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
# 组合模式
|
||||||
|
## 简介
|
||||||
|
组合模式对单个对象(叶子对象)和组合对象(组合对象)具有一致性,它将对象组织到树结构中,可以用来描述整体与部分的关
|
||||||
|
系。同时它也模糊了简单元素(叶子对象)和复杂元素(容器对象)的概念,使得客户能够像处理简单元素一样来处理复杂元素,
|
||||||
|
从而使客户程序能够与复杂元素的内部结构解耦。组合模式使用面向对象的思想来实现树形结构的构建与处理,描述了如何将
|
||||||
|
容器对象和叶子对象进行递归组合,实现简单,灵活性好。由于在软件开发中存在大量的树形结构,因此组合模式是一种使用
|
||||||
|
频率较高的结构型设计模式,Java SE 中的 AWT 和 Swing包的设计就基于组合模式,在这些界面包中为用户提供了大量的容
|
||||||
|
器构件(如Container)和成员构件(如 Checkbox、Button 和 TextComponent等)。
|
||||||
|
|
||||||
|
## 结构
|
||||||
|
|
||||||
|
![组合模式](https://github.com/lzh984294471/designPattern/raw/master/pics/composite.jpg)
|
||||||
|
|
||||||
|
## 组合模式的优点
|
||||||
|
|
||||||
|
(1) 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层
|
||||||
|
次结构进行控制。
|
||||||
|
(2) 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。
|
||||||
|
(3) 在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
|
||||||
|
(4) 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的
|
||||||
|
树形结构,但对树形结构的控制却非常简单。
|
||||||
|
|
||||||
|
## 组合模式的缺点
|
||||||
|
|
||||||
|
在增加新构件时很难对容器中的构件类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件
|
||||||
|
夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,在这种情况
|
||||||
|
下,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂。
|
||||||
|
|
||||||
|
## 适用场景
|
||||||
|
|
||||||
|
(1) 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们。
|
||||||
|
(2) 在一个使用面向对象语言开发的系统中需要处理一个树形结构。
|
||||||
|
(3) 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型。
|
||||||
|
|
20
src/main/java/com/zeekling/composite/test/Test.java
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
package composite.composite.test;
|
||||||
|
|
||||||
|
import com.zeekling.composite.Component;
|
||||||
|
import com.zeekling.composite.Composite;
|
||||||
|
import com.zeekling.composite.Part;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组合模式
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Component composite = new Composite("composite");
|
||||||
|
Component one = new Part("part one");
|
||||||
|
Component two = new Part("part two");
|
||||||
|
composite.add(one);
|
||||||
|
composite.add(two);
|
||||||
|
composite.display();
|
||||||
|
}
|
||||||
|
}
|
18
src/main/java/com/zeekling/decorate/Change.java
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
package com.zeekling.decorate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class Change implements Decorate{
|
||||||
|
|
||||||
|
private Decorate decorate;
|
||||||
|
|
||||||
|
public Change(Decorate decorate){
|
||||||
|
this.decorate = decorate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void act() {
|
||||||
|
decorate.act();
|
||||||
|
}
|
||||||
|
}
|
20
src/main/java/com/zeekling/decorate/ChangeOne.java
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
package com.zeekling.decorate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class ChangeOne extends Change {
|
||||||
|
|
||||||
|
public ChangeOne(Decorate decorate) {
|
||||||
|
super(decorate);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void act() {
|
||||||
|
super.act();
|
||||||
|
say();
|
||||||
|
System.out.println("ChangeOne");
|
||||||
|
}
|
||||||
|
public void say(){
|
||||||
|
System.out.println("say");
|
||||||
|
}
|
||||||
|
}
|
22
src/main/java/com/zeekling/decorate/ChangeTwo.java
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
package com.zeekling.decorate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class ChangeTwo extends Change {
|
||||||
|
|
||||||
|
public ChangeTwo(Decorate decorate) {
|
||||||
|
super(decorate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void act() {
|
||||||
|
super.act();
|
||||||
|
eat();
|
||||||
|
System.out.println("changeTwo");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void eat(){
|
||||||
|
System.out.println("eat");
|
||||||
|
}
|
||||||
|
}
|
10
src/main/java/com/zeekling/decorate/Decorate.java
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
package com.zeekling.decorate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public interface Decorate {
|
||||||
|
|
||||||
|
void act();
|
||||||
|
|
||||||
|
}
|
11
src/main/java/com/zeekling/decorate/DecorateObject.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
package com.zeekling.decorate;
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class DecorateObject implements Decorate {
|
||||||
|
@Override
|
||||||
|
public void act() {
|
||||||
|
System.out.println("猜猜我是谁");
|
||||||
|
}
|
||||||
|
}
|
15
src/main/java/com/zeekling/decorate/readme.md
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
# 装饰器模式
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。
|
||||||
|
|
||||||
|
## 装饰器模式类图
|
||||||
|
![装饰器模式类图](http://www.zeekling.cn/gogs/zeek/designPattern/raw/master/pics/decorator.png)
|
||||||
|
|
||||||
|
## 主要角色
|
||||||
|
* 抽象构建角色:给出一个抽象接口,以规范准备接受附加责任的对象。
|
||||||
|
* 具体构件角色:定义一个将要接受附加责任的类。
|
||||||
|
* 装饰角色:持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
|
||||||
|
* 具体装饰器角色:负责给构件对象“贴上”附加的责任。
|
||||||
|
|
||||||
|
|
19
src/main/java/com/zeekling/decorate/test/Test.java
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
package decorate.decorate.test;
|
||||||
|
|
||||||
|
import com.zeekling.decorate.ChangeOne;
|
||||||
|
import com.zeekling.decorate.ChangeTwo;
|
||||||
|
import com.zeekling.decorate.Decorate;
|
||||||
|
import com.zeekling.decorate.DecorateObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Decorate decorate = new DecorateObject();
|
||||||
|
Decorate changeOne = new ChangeOne(decorate);
|
||||||
|
Decorate changeTwo = new ChangeTwo(decorate);
|
||||||
|
changeOne.act();
|
||||||
|
changeTwo.act();
|
||||||
|
}
|
||||||
|
}
|
9
src/main/java/com/zeekling/facade/Baidu.java
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
package com.zeekling.facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public interface Baidu {
|
||||||
|
void computerShutdown();
|
||||||
|
void searchSomething();
|
||||||
|
}
|
19
src/main/java/com/zeekling/facade/BaiduImp.java
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
package com.zeekling.facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class BaiduImp implements Baidu {
|
||||||
|
@Override
|
||||||
|
public void computerShutdown() {
|
||||||
|
Computer computer = new ComputerImp();
|
||||||
|
computer.shutdown();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void searchSomething() {
|
||||||
|
Search search = new SearchImp();
|
||||||
|
search.search();
|
||||||
|
}
|
||||||
|
}
|
8
src/main/java/com/zeekling/facade/Computer.java
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
package com.zeekling.facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public interface Computer {
|
||||||
|
void shutdown();
|
||||||
|
}
|
11
src/main/java/com/zeekling/facade/ComputerImp.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
package com.zeekling.facade;
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class ComputerImp implements Computer {
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
System.out.println("computer closed ");
|
||||||
|
}
|
||||||
|
}
|
8
src/main/java/com/zeekling/facade/Search.java
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
package com.zeekling.facade;
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public interface Search {
|
||||||
|
void search();
|
||||||
|
}
|
11
src/main/java/com/zeekling/facade/SearchImp.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
package com.zeekling.facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class SearchImp implements Search {
|
||||||
|
@Override
|
||||||
|
public void search() {
|
||||||
|
System.out.println("search something ");
|
||||||
|
}
|
||||||
|
}
|
23
src/main/java/com/zeekling/facade/readme.md
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
# 外观模式
|
||||||
|
## 简介
|
||||||
|
外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。
|
||||||
|
## 模式结构
|
||||||
|
|
||||||
|
![外观模式](https://github.com/lzh984294471/designPattern/raw/master/pics/facade.jpg)
|
||||||
|
## 优点
|
||||||
|
* 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。
|
||||||
|
* 实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。
|
||||||
|
* 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。
|
||||||
|
* 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。
|
||||||
|
|
||||||
|
## 缺点
|
||||||
|
* 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
|
||||||
|
* 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。
|
||||||
|
|
||||||
|
## 使用环境
|
||||||
|
* 当要为一个复杂子系统提供一个简单接口时可以使用外观模式。该接口可以满足大多数用户的需求,而且用户也可以越过外观类直接访问子系统。
|
||||||
|
* 客户程序与多个子系统之间存在很大的依赖性。引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性。
|
||||||
|
* 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。
|
||||||
|
|
||||||
|
## 应用
|
||||||
|
|
19
src/main/java/com/zeekling/facade/test/Test.java
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
package facade.facade.test;
|
||||||
|
|
||||||
|
import com.zeekling.facade.Baidu;
|
||||||
|
import com.zeekling.facade.BaiduImp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/29/16.
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
/**
|
||||||
|
* 外观模式
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Baidu baidu = new BaiduImp();
|
||||||
|
baidu.computerShutdown();
|
||||||
|
baidu.searchSomething();
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/com/zeekling/flyweight/ConcreteFlyweight.java
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
package com.zeekling.flyweight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
* 具体享元
|
||||||
|
*/
|
||||||
|
public class ConcreteFlyweight implements Flyweight{
|
||||||
|
String in;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param in 内部享元
|
||||||
|
*/
|
||||||
|
public ConcreteFlyweight(String in){
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param out 外部享元
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void say(String out) {
|
||||||
|
System.out.println(out+": i am out ");
|
||||||
|
System.out.println(in+":i am in ");
|
||||||
|
}
|
||||||
|
}
|
9
src/main/java/com/zeekling/flyweight/Flyweight.java
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
package com.zeekling.flyweight;
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
* 具体享元
|
||||||
|
*/
|
||||||
|
public interface Flyweight {
|
||||||
|
void say(String out);
|
||||||
|
}
|
21
src/main/java/com/zeekling/flyweight/FlyweightFactory.java
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
package com.zeekling.flyweight;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
* 享元工厂
|
||||||
|
*/
|
||||||
|
public class FlyweightFactory {
|
||||||
|
private static Hashtable<String,Flyweight> flyweights = new Hashtable<>();
|
||||||
|
public static Flyweight factory(String in){
|
||||||
|
Flyweight flyweight ;
|
||||||
|
flyweight = flyweights.get(in);
|
||||||
|
if(null == flyweight){
|
||||||
|
flyweight = new ConcreteFlyweight(in);
|
||||||
|
flyweights.put(in,flyweight);
|
||||||
|
}
|
||||||
|
return flyweight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
src/main/java/com/zeekling/flyweight/readme.md
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
# 享元模式
|
||||||
|
## 简述
|
||||||
|
享元模式采用一个共享来避免大量拥有相同内容对象的开销。这种开销最常见、最直观的就是内容的消耗。享元对象能够做到共享的关键是区分内蕴态和外蕴态。 <br>
|
||||||
|
一个内蕴状态是存储在享元对象内部的,并且是不会随着环境的改变而有所不同。因此,一个享元可以具有内蕴状态并可以共享。<br>
|
||||||
|
一个外蕴状态是随着环境的改变的、不可共享的。享元对象的外蕴状态必须有客户端保存,并在享元对象被创建之后,在需要使用的时候在传入享元对象内部。
|
||||||
|
外蕴状态不可以影响到享元对象的内蕴状态,他们是相互独立的<br>
|
||||||
|
享元模式可以分为单纯享元模式和复合享元模式。<br>
|
||||||
|
|
||||||
|
## 单纯享元模式
|
||||||
|
在单纯享元模式中,所有的对象都是可以共享。<br>
|
||||||
|
|
||||||
|
![单纯享元模式](https://github.com/lzh984294471/designPattern/raw/master/pics/flyweight1.png)
|
||||||
|
|
||||||
|
### 单纯享元模式中所涉及到的角色:
|
||||||
|
|
||||||
|
* 抽象享元角色:给出一个抽象接口,以规定所有具体的享元角色需要实现的方法。
|
||||||
|
* 具体享元角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
|
||||||
|
* 享元工厂角色:本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当的共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会
|
||||||
|
检查系统中是否已经存在有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个合适的享元对象的话,享
|
||||||
|
元工厂角色就应当创建一个合适的享元角色。
|
||||||
|
|
||||||
|
## 复合享元模式
|
||||||
|
|
||||||
|
### 简述
|
||||||
|
在单纯享元模式中,所有的享元对象都是单纯享元对象,也就是都可以直接共享的。还有一种较为复杂的情况,将一些单纯享元使用合成模式加以复用,形成复合享
|
||||||
|
元对象。这样的复合享元对象本身不能共享,但是他们可以分解成单纯享元对象,而后者则可以共享。<br>
|
||||||
|
|
||||||
|
![复合享元模式](https://github.com/lzh984294471/designPattern/raw/master/pics/flyweight2.png) <br>
|
||||||
|
|
||||||
|
### 复合享元角色所涉及的角色:
|
||||||
|
|
||||||
|
* 抽象享元角色:给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
|
||||||
|
* 实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
|
||||||
|
* 复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。
|
||||||
|
* 本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否
|
||||||
|
已经有 一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创
|
||||||
|
建一个 合适的享元对象。
|
||||||
|
|
15
src/main/java/com/zeekling/flyweight/test/Test.java
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
package flyweight.flyweight.test;
|
||||||
|
|
||||||
|
import com.zeekling.flyweight.Flyweight;
|
||||||
|
import com.zeekling.flyweight.FlyweightFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/30/16.
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Flyweight flyweight = FlyweightFactory.factory("lzh");
|
||||||
|
flyweight.say("out");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
16
src/main/java/com/zeekling/handler/ConcreteHandler.java
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
package com.zeekling.handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
*/
|
||||||
|
public class ConcreteHandler extends Handler {
|
||||||
|
@Override
|
||||||
|
public void requestHandler() {
|
||||||
|
if(getHandler() != null){
|
||||||
|
System.out.println("let off request");
|
||||||
|
getHandler().requestHandler();
|
||||||
|
}else {
|
||||||
|
System.out.println("deal with request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/main/java/com/zeekling/handler/Handler.java
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
package com.zeekling.handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
* 责任链模式
|
||||||
|
*/
|
||||||
|
public abstract class Handler {
|
||||||
|
private Handler handler;
|
||||||
|
public abstract void requestHandler();
|
||||||
|
|
||||||
|
public void setHandler(Handler handler) {
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Handler getHandler() {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
13
src/main/java/com/zeekling/handler/readme.md
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
# 责任链模式
|
||||||
|
## 简述
|
||||||
|
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,
|
||||||
|
直到有一个对象处理他为止。
|
||||||
|
## 角色
|
||||||
|
### 抽象处理者角色(Handler)
|
||||||
|
定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。
|
||||||
|
### 具体处理者角色(ConcreteHandler)
|
||||||
|
具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
|
||||||
|
## 类图
|
||||||
|
![责任链模式](https://github.com/lzh984294471/designPattern/raw/master/pics/handler.png) <br>
|
||||||
|
|
||||||
|
|
16
src/main/java/com/zeekling/handler/test/Test.java
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
package handler.handler.test;
|
||||||
|
|
||||||
|
import com.zeekling.handler.ConcreteHandler;
|
||||||
|
import com.zeekling.handler.Handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Handler handler1 = new ConcreteHandler();
|
||||||
|
Handler handler2 = new ConcreteHandler();
|
||||||
|
handler1.setHandler(handler2);
|
||||||
|
handler1.requestHandler();
|
||||||
|
}
|
||||||
|
}
|
0
src/main/java/com/zeekling/interpreter/readme.md
Normal file
7
src/main/java/com/zeekling/iterator/Aggregate.java
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
package com.zeekling.iterator;
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
*/
|
||||||
|
public abstract class Aggregate {
|
||||||
|
public abstract Iterator createIterator();
|
||||||
|
}
|
25
src/main/java/com/zeekling/iterator/AggregateImp.java
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
package com.zeekling.iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
*/
|
||||||
|
public class AggregateImp extends Aggregate {
|
||||||
|
private Object[] objects = null;
|
||||||
|
public AggregateImp(Object[] objects){
|
||||||
|
this.objects = objects;
|
||||||
|
}
|
||||||
|
public Object getElement(int index){
|
||||||
|
if(index < objects.length){
|
||||||
|
return objects[index];
|
||||||
|
}else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Iterator createIterator() {
|
||||||
|
return new IteratorImp(this);
|
||||||
|
}
|
||||||
|
public int getSize(){
|
||||||
|
return objects.length;
|
||||||
|
}
|
||||||
|
}
|
11
src/main/java/com/zeekling/iterator/Iterator.java
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
package com.zeekling.iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
*/
|
||||||
|
public interface Iterator {
|
||||||
|
void next();
|
||||||
|
boolean isLast();
|
||||||
|
void first();
|
||||||
|
Object current();
|
||||||
|
}
|
36
src/main/java/com/zeekling/iterator/IteratorImp.java
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
package com.zeekling.iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
*/
|
||||||
|
public class IteratorImp implements Iterator {
|
||||||
|
private AggregateImp aggregateImp = null;
|
||||||
|
private int size = 0;
|
||||||
|
private int index = 0;
|
||||||
|
public IteratorImp(AggregateImp aggregateImp){
|
||||||
|
this.aggregateImp = aggregateImp;
|
||||||
|
this.size = aggregateImp.getSize();
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void next() {
|
||||||
|
if(index < size){
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLast() {
|
||||||
|
return index>=size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void first() {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object current() {
|
||||||
|
return aggregateImp.getElement(index);
|
||||||
|
}
|
||||||
|
}
|
32
src/main/java/com/zeekling/iterator/readme.md
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
# 迭代子模式
|
||||||
|
## 简述
|
||||||
|
迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。<br>
|
||||||
|
迭代子可分为外禀迭代子和内禀迭代子。<br>
|
||||||
|
迭代子模式有两种实现方式,分别是白箱聚集与外禀迭代子和黑箱聚集于内禀迭代子。<br>
|
||||||
|
|
||||||
|
## 类图
|
||||||
|
|
||||||
|
![迭代子模式](https://github.com/lzh984294471/designPattern/raw/master/pics/iterator.jpg)
|
||||||
|
|
||||||
|
## 结构
|
||||||
|
|
||||||
|
* 抽象容器:一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
|
||||||
|
* 具体容器:就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,
|
||||||
|
Set接口的哈希列表的实现HashSet等。
|
||||||
|
* 抽象迭代器:定义遍历元素所需要的方法,一般来说会有这么三个方法:取得第一个元素的方法first(),取得下
|
||||||
|
一个元素的方法next(),判断是否遍历结束的方法isDone()(或者叫hasNext()),移出当前对象的方法remove().
|
||||||
|
* 迭代器实现:实现迭代器接口中定义的方法,完成集合的迭代。
|
||||||
|
|
||||||
|
## 优缺点
|
||||||
|
### 优点
|
||||||
|
* 简化了遍历方式,对于对象集合的遍历,还是比较麻烦的,对于数组或者有序列表,我们尚可以通过游标来取得,
|
||||||
|
但用户需要在对集合了解很清楚的前提下,自行遍历对象,但是对于hash表来说,用户遍历起来就比较麻烦了。而引
|
||||||
|
入了迭代器方法后,用户用起来就简单的多了。
|
||||||
|
* 可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来
|
||||||
|
只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。
|
||||||
|
* 封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心。
|
||||||
|
|
||||||
|
### 缺点
|
||||||
|
|
||||||
|
* 对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,
|
||||||
|
我们宁可愿意使用for循环和get方法来遍历集合。
|
20
src/main/java/com/zeekling/iterator/test/Test.java
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
package iterator.iterator.test;
|
||||||
|
|
||||||
|
import com.zeekling.iterator.AggregateImp;
|
||||||
|
import com.zeekling.iterator.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 3/31/16.
|
||||||
|
* 迭代子模式
|
||||||
|
*/
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Object[] object = {1,2,3,4,5,6,7};
|
||||||
|
AggregateImp aggregateImp = new AggregateImp(object);
|
||||||
|
Iterator iterator = aggregateImp.createIterator();
|
||||||
|
while(!iterator.isLast()){
|
||||||
|
System.out.print(iterator.current()+"\t");
|
||||||
|
iterator.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
0
src/main/java/com/zeekling/mediator/readme.md
Normal file
15
src/main/java/com/zeekling/memento/Caretaker.java
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
package com.zeekling.memento;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lzh on 4/1/16.
|
||||||
|
*/
|
||||||
|
public class Caretaker {
|
||||||
|
private Memento memento;
|
||||||
|
|
||||||
|
public Memento getMemento() {
|
||||||
|
return memento;
|
||||||
|
}
|
||||||
|
public void saveMemento(Memento memento){
|
||||||
|
this.memento = memento;
|
||||||
|
}
|
||||||
|
}
|
17
src/main/java/com/zeekling/memento/Memento.java
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
package com.zeekling.memento;
|
||||||
|
/**
|
||||||
|
* Created by lzh on 4/1/16.
|
||||||
|
*/
|
||||||
|
public class Memento {
|
||||||
|
private String msg;
|
||||||
|
public Memento(String msg){
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
public String getMsg(){
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
}
|
20
src/main/java/com/zeekling/memento/Originator.java
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
package com.zeekling.memento;
|
||||||
|
/**
|
||||||
|
* Created by lzh on 4/1/16.
|
||||||
|
* 备忘录模式
|
||||||
|
*/
|
||||||
|
public class Originator {
|
||||||
|
private String msg;
|
||||||
|
public Memento createMemento(String msg){
|
||||||
|
this.msg = msg;
|
||||||
|
return new Memento(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
24
src/main/java/com/zeekling/memento/readme.md
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
# 备忘录模式
|
||||||
|
## 简述
|
||||||
|
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态
|
||||||
|
捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
|
||||||
|
|
||||||
|
## 类图
|
||||||
|
|
||||||
|
![备忘录模式](https://github.com/lzh984294471/designPattern/raw/master/pics/memento.png)
|
||||||
|
|
||||||
|
## 优点
|
||||||
|
|
||||||
|
1. 有时一些发起人对象的内部信息在发起人对象以外的地方,当必须又发起人自己读取,这时备忘录模式可以把复杂的
|
||||||
|
发起人的内部信息对其他对象屏蔽起来从而恰当的保持封装的边界。
|
||||||
|
2. 本模式简化了发起人,发起人不需要管理和保存内部状态的一个个版本。客户端可以自行的管理他们所需要的这些状
|
||||||
|
态的版本
|
||||||
|
3. 发起人角色状态改变时,有可能这个状态无效,这时候可以使用暂时存储起来的备忘录讲状态复原。
|
||||||
|
|
||||||
|
|
||||||
|
## 缺点
|
||||||
|
|
||||||
|
1. 如果发起人角色的状态需要完整的存到备忘录对象中,那么在资源消耗上备忘录可能很昂贵。
|
||||||
|
2. 当负责人将一个对象存储起来的时候,负责人可能并不知道这个状态占用太多的存储空间,从而无法提醒用户一个操作是否昂
|
||||||
|
贵。
|
||||||
|
3. 当发起人角色改变的时候,有可能这个协议无效。如果状态改变的成功率不高的话,不如采取“假如”协议模式。
|