Skip to content

Commit daff649

Browse files
committed
update post 设计模式
1 parent c2a979e commit daff649

File tree

2 files changed

+310
-4
lines changed

2 files changed

+310
-4
lines changed

_posts/2019-05-16-设计模式.md

+310-4
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ class BridgePattern {
381381
}
382382
}
383383
```
384-
#### [组合模式]
384+
#### 组合模式
385385
把多个对象组成树状结构来表示局部与整体,这样用户可以一样的对待单个对象和对象的组合。
386386

387387
如文件如文件夹都看作一个条目,就形成目录结构。
@@ -501,7 +501,7 @@ public class Main {
501501
}
502502
```
503503
参考书籍:图解设计模式(ISBN国际标准书号: 9787115439499)
504-
#### [修饰模式]
504+
#### [修饰模式] (装饰模式)
505505
向某个对象动态地添加更多的功能。修饰模式是除类继承外另一种扩展功能的方法。
506506
```java
507507
// The Window interface class
@@ -599,7 +599,7 @@ description:simple window
599599
description:simple window, including horizontal scrollbars
600600
description:simple window, including horizontal scrollbars, including vertical scrollbars
601601
```
602-
#### [外观模式]
602+
#### [外观模式] (门面模式)
603603
为子系统中的一组接口提供一个一致的界面, 外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
604604
```java
605605
// 这是一个抽象的示例。一个客户“you”通过外观接口“computer”启动计算机。
@@ -649,9 +649,307 @@ class You {
649649
```
650650
#### [享元模式]
651651
通过共享以便有效的支持大量小颗粒对象。
652+
```java
653+
// 享元模式利用只加载执行任务时所必需的最少资料,因而减少内存使用量。
654+
public enum FontEffect {
655+
BOLD, ITALIC, SUPERSCRIPT, SUBSCRIPT, STRIKETHROUGH
656+
}
657+
658+
public final class FontData {
659+
// A weak hash map will drop unused references to FontData.
660+
// Values have to be wrapped in WeakReferences,
661+
// because value objects in weak hash map are held by strong references.
662+
private static final WeakHashMap<FontData, WeakReference<FontData>> FLY_WEIGHT_DATA =
663+
new WeakHashMap<FontData, WeakReference<FontData>>();
664+
private final int pointSize;
665+
private final String fontFace;
666+
private final Color color;
667+
private final Set<FontEffect> effects;
668+
669+
private FontData(int pointSize, String fontFace, Color color, EnumSet<FontEffect> effects) {
670+
this.pointSize = pointSize;
671+
this.fontFace = fontFace;
672+
this.color = color;
673+
this.effects = Collections.unmodifiableSet(effects);
674+
}
675+
676+
public static FontData create(int pointSize, String fontFace, Color color,
677+
FontEffect... effects) {
678+
EnumSet<FontEffect> effectsSet = EnumSet.noneOf(FontEffect.class);
679+
for (FontEffect fontEffect : effects) {
680+
effectsSet.add(fontEffect);
681+
}
682+
// We are unconcerned with object creation cost, we are reducing overall memory consumption
683+
// 我们不关心对象创建成本,我们在减少整体内存消耗
684+
FontData data = new FontData(pointSize, fontFace, color, effectsSet);
685+
686+
// Retrieve previously created instance with the given values if it (still) exists
687+
// 如果给定的值仍然存在的话,恢复先前创建的实例
688+
WeakReference<FontData> ref = FLY_WEIGHT_DATA.get(data);
689+
FontData result = (ref != null) ? ref.get() : null;
690+
691+
// Store new font data instance if no matching instance exists
692+
// 如果没有匹配的实例存在的话,存储新的字体数据实例
693+
if (result == null) {
694+
FLY_WEIGHT_DATA.put(data, new WeakReference<FontData> (data));
695+
result = data;
696+
}
697+
// return the single immutable copy with the given values
698+
return result;
699+
}
700+
701+
@Override
702+
public boolean equals(Object obj) {
703+
if (obj instanceof FontData) {
704+
if (obj == this) {
705+
return true;
706+
}
707+
FontData other = (FontData) obj;
708+
return other.pointSize == pointSize && other.fontFace.equals(fontFace)
709+
&& other.color.equals(color) && other.effects.equals(effects);
710+
}
711+
return false;
712+
}
713+
714+
@Override
715+
public int hashCode() {
716+
return (pointSize * 37 + effects.hashCode() * 13) * fontFace.hashCode();
717+
}
718+
719+
// Getters for the font data, but no setters. FontData is immutable.
720+
}
721+
```
652722
#### [代理模式]
653723
为其他对象提供一个代理以控制对这个对象的访问。
724+
```java
725+
// ProxyImage 类别用来访问远程方法。
726+
interface Image {
727+
void displayImage();
728+
}
729+
730+
//on System A
731+
class RealImage implements Image {
732+
private String filename;
733+
public RealImage(String filename) {
734+
this.filename = filename;
735+
loadImageFromDisk();
736+
}
737+
private void loadImageFromDisk() {
738+
System.out.println("Loading " + filename);
739+
}
740+
public void displayImage() {
741+
System.out.println("Displaying " + filename);
742+
}
743+
}
744+
745+
//on System B
746+
class ProxyImage implements Image {
747+
private String filename;
748+
private Image image;
749+
public ProxyImage(String filename) {
750+
this.filename = filename;
751+
}
752+
public void displayImage() {
753+
if(image == null)
754+
image = new RealImage(filename);
755+
image.displayImage();
756+
}
757+
}
758+
759+
class ProxyExample {
760+
public static void main(String[] args) {
761+
Image image1 = new ProxyImage("HiRes_10MB_Photo1");
762+
Image image2 = new ProxyImage("HiRes_10MB_Photo2");
763+
764+
image1.displayImage(); // loading necessary
765+
image2.displayImage(); // loading necessary
766+
}
767+
}
768+
```
769+
```text
770+
程序的输出为:
771+
Loading HiRes_10MB_Photo1
772+
Displaying HiRes_10MB_Photo1
773+
Loading HiRes_10MB_Photo2
774+
Displaying HiRes_10MB_Photo2
775+
```
776+
654777
## [行为型模式]
778+
#### [责任链模式]
779+
为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。
780+
将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
781+
```java
782+
// 以下的日志类(logging)例子演示了该模式。
783+
// 注意:该例子不是日志类的推荐实现方式。
784+
// 每一个logging handler首先决定是否需要在该层做处理,然后将控制传递到下一个logging handler。
785+
// 通常在责任链模式的实现中,如果在某一层已经处理了这个logger,那么这个logger就不会传递下去。
786+
// 在我们这个例子中,消息会一直传递到最底层不管它是否已经被处理。
787+
788+
import java.util.*;
789+
790+
abstract class Logger
791+
{
792+
public static int ERR = 3;
793+
public static int NOTICE = 5;
794+
public static int DEBUG = 7;
795+
protected int mask;
796+
// The next element in the chain of responsibility
797+
protected Logger next;
798+
public Logger setNext( Logger l){
799+
next = l;
800+
return this;
801+
}
802+
public final void message( String msg, int priority ){
803+
if ( priority <= mask ) {
804+
writeMessage( msg );
805+
if ( next != null ) {
806+
next.message( msg, priority );
807+
}
808+
}
809+
}
810+
protected abstract void writeMessage( String msg );
811+
}
812+
813+
class StdoutLogger extends Logger {
814+
public StdoutLogger( int mask ) { this.mask = mask; }
815+
protected void writeMessage( String msg ){
816+
System.out.println( "Writting to stdout: " + msg );
817+
}
818+
}
819+
820+
class EmailLogger extends Logger {
821+
public EmailLogger( int mask ) { this.mask = mask; }
822+
protected void writeMessage( String msg ){
823+
System.out.println( "Sending via email: " + msg );
824+
}
825+
}
826+
827+
class StderrLogger extends Logger {
828+
public StderrLogger( int mask ) { this.mask = mask; }
829+
protected void writeMessage( String msg ){
830+
System.out.println( "Sending to stderr: " + msg );
831+
}
832+
}
833+
834+
public class ChainOfResponsibilityExample{
835+
public static void main( String[] args )
836+
{
837+
// Build the chain of responsibility
838+
Logger l = new StdoutLogger( Logger.DEBUG).setNext(
839+
new EmailLogger( Logger.NOTICE ).setNext(
840+
new StderrLogger( Logger.ERR ) ) );
841+
// Handled by StdoutLogger
842+
l.message( "Entering function y.", Logger.DEBUG );
843+
// Handled by StdoutLogger and EmailLogger
844+
l.message( "Step1 completed.", Logger.NOTICE );
845+
// Handled by all three loggers
846+
l.message( "An error has occurred.", Logger.ERR );
847+
}
848+
}
849+
```
850+
```text
851+
程序的输出是:
852+
Writing to debug output: Entering function y.
853+
Writing to debug output: Step1 completed.
854+
Sending via e-mail: Step1 completed.
855+
Writing to debug output: An error has occurred.
856+
Sending via e-mail: An error has occurred.
857+
Writing to stderr: An error has occurred.
858+
```
859+
#### [命令模式]
860+
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可取消的操作。
861+
862+
图片来源:[wiki](https://upload.wikimedia.org/wikipedia/commons/8/8e/Command_Design_Pattern_Class_Diagram.png)
863+
864+
![例子](/img/post/命令模式例子类图.png)
865+
```java
866+
import java.util.List;
867+
import java.util.ArrayList;
868+
869+
/* The Command interface */
870+
public interface Command {
871+
void execute();
872+
}
873+
874+
/* The Invoker class */
875+
public class Switch {
876+
private List<Command> history = new ArrayList<Command>();
877+
public Switch() { }
878+
public void storeAndExecute(Command cmd) {
879+
this.history.add(cmd); // optional
880+
cmd.execute();
881+
}
882+
}
883+
884+
/* The Receiver class */
885+
public class Light {
886+
public Light() { }
887+
public void turnOn() { System.out.println("The light is on"); }
888+
public void turnOff() { System.out.println("The light is off"); }
889+
}
890+
891+
/* The Command for turning on the light - ConcreteCommand #1 */
892+
public class FlipUpCommand implements Command {
893+
private Light theLight;
894+
public FlipUpCommand(Light light) { this.theLight = light; }
895+
public void execute(){ theLight.turnOn(); }
896+
}
897+
898+
/* The Command for turning off the light - ConcreteCommand #2 */
899+
public class FlipDownCommand implements Command {
900+
private Light theLight;
901+
public FlipDownCommand(Light light) { this.theLight = light; }
902+
public void execute() { theLight.turnOff(); }
903+
}
904+
905+
/* The test class or client */
906+
public class PressSwitch {
907+
public static void main(String[] args){
908+
Light lamp = new Light();
909+
Command switchUp = new FlipUpCommand(lamp);
910+
Command switchDown = new FlipDownCommand(lamp);
911+
912+
Switch mySwitch = new Switch();
913+
try {
914+
if ("ON".equalsIgnoreCase(args[0])) {
915+
mySwitch.storeAndExecute(switchUp);
916+
} else if ("OFF".equalsIgnoreCase(args[0])) {
917+
mySwitch.storeAndExecute(switchDown);
918+
} else {
919+
System.out.println("Argument \"ON\" or \"OFF\" is required.");
920+
}
921+
} catch (Exception e) {
922+
System.out.println("Arguments required.");
923+
}
924+
}
925+
}
926+
```
927+
#### 解释器模式
928+
给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
929+
#### [迭代器模式]
930+
提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
931+
#### [中介者模式]
932+
包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶合。
933+
当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。
934+
#### 备忘录模式
935+
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,
936+
将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
937+
#### [观察者模式]
938+
在对象间定义一个一对多的联系性,由此当一个对象改变了状态,所有其他相关的对象会被通知并且自动刷新。
939+
#### 状态模式
940+
让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能获取的状态创立一个状态类的子类。
941+
当系统的状态变化时,系统便改变所选的子类。
942+
#### [策略模式]
943+
定义一个算法的系列,将其各个分装,并且使他们有交互性。策略模式使得算法在用户使用的时候能独立的改变。
944+
#### [模板方法模式]
945+
模板方法模式准备一个抽象类,将部分逻辑以具体方法及具体构造子类的形式实现,
946+
然后声明一些抽象方法来迫使子类实现剩余的逻辑。
947+
不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。
948+
先构建一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
949+
#### [访问者模式]
950+
封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改,接受这个操作的数据结构可以保持不变。
951+
访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,
952+
使得操作集合可以相对自由的演化。
655953

656954
---
657955
## 常见问题
@@ -677,10 +975,18 @@ class You {
677975

678976
[适配器模式]: https://zh.wikipedia.org/wiki/适配器模式
679977
[桥接模式]: https://zh.wikipedia.org/wiki/桥接模式
680-
[组合模式]: https://zh.wikipedia.org/wiki/组合模式
681978
[修饰模式]: https://zh.wikipedia.org/wiki/修饰模式
682979
[外观模式]: https://zh.wikipedia.org/wiki/外观模式
683980
[享元模式]: https://zh.wikipedia.org/wiki/享元模式
684981
[代理模式]: https://zh.wikipedia.org/wiki/代理模式
685982

983+
[责任链模式]: https://zh.wikipedia.org/wiki/责任链模式
984+
[命令模式]: https://zh.wikipedia.org/wiki/命令模式
985+
[迭代器模式]: https://zh.wikipedia.org/wiki/迭代器模式
986+
[中介者模式]: https://zh.wikipedia.org/wiki/中介者模式
987+
[观察者模式]: https://zh.wikipedia.org/wiki/观察者模式
988+
[策略模式]: https://zh.wikipedia.org/wiki/策略模式
989+
[模板方法模式]: https://zh.wikipedia.org/wiki/模板方法
990+
[访问者模式]: https://zh.wikipedia.org/wiki/访问者模式
991+
686992
[IBM-开发社区-适配器模式]: https://www.ibm.com/developerworks/cn/java/j-lo-adapter-pattern/index.html

img/post/命令模式例子类图.png

27 KB
Loading

0 commit comments

Comments
 (0)