Design Pattern

Strategy 策略模式

做一件事情有不同的执行方法时

典型案例:不同类型对象的排序:Comparator 接口

对于自定义类的排序,排序的策略肯定不同,使用Arrays.sort(T[] a, Comparator<? super T> c)排序时需要将一个Comparator对象传入,可以建立一个类去实现Comparator接口,也可以用匿名内部类以及lambda表示式

1
2
3
4
5
6
7
8
9
10
11
Cat[] cats = {new Cat(4, 5), new Cat(6, 2), new Cat(3, 8)};
Arrays.sort(cats, new Comparator<Cat> () {
@Override
public int compare(Cat o1, Cat o2) {
return 0;
}
});
// lambda 表示式代替匿名内部类
Arrays.sort(cats, (c1, c2)->{
return c1.getWeight() - c2.getWeight();
});

Factory Method & Abstract Method 工厂方法和抽象工厂

Mediator 调停者

消息中间件

Decorator 装饰器

Chain Of Responsibility 责任链

要对某件事情做一系列不同操作,如果将这些操作都写在一起,代码很多逻辑很乱,将每个操作单独在一个类中,方便扩展;将这些操作用一个链条串起来,链条之间也可以串起来,就构成了责任链

单独封装

有一个可能包含敏感词汇或非法字符的字符串 s,要对 s 进行过滤,使 s 合法,敏感词汇是随着时间变化的,我们希望方便灵活的制定过滤规则,首先将不同的过滤器单独的制定出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface Filter {
boolean doFilter(String s);
}
class SensitiveFilter implements Filter{
@Override
public boolean doFilter(String s) {
s = s.replaceAll("炸弹", "");
return true;
}
}
class ScriptFilter implements Filter {
@Override
public boolean doFilter(String s) {
s = s.replaceAll("<", "]").replaceAll(">", "]");
return true;
}
}

链条

将过滤器都放进一个链条中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class FillterChain {
List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f) {
this.filters.add(f);
return this;
}
public boolean doFilter(String s) {
for (Filter f : filters) {
if (!f.doFilter(s))
return false;
}
return true;
}
}

执行

1
2
3
4
5
6
7
public static void main(String[] args) {
String s = "...";
FilterChain chain = new FilterChain();
chain.add(new ScriptFilter()).add(new SensitiveFilter());
chain.doFilter(s);
System.out.println(s);
}

Observer 观察者

事件处理模型,当一个 source (源对象,被观察的对象) 发出某个Event(动作,事件)时,Observer(观察者)对这个动作做出反应

源对象

将观察者列表作为属性,有添加观察者,执行观察者的方法;在执行观察者方法时要创建对应的事件,并传入观察者的执行方法中

1
2
3
4
5
6
7
8
9
10
11
12
13
class Button {
private List<ButtonListener> buttonListeners = new ArrayList<>();
public void buttonPress() {
ActionEvent event = new ActionEvent(System.currentTimeMillis(), this);
for (ButtonListener listener:buttonListeners) {
listener.actionPerformed(event);
}
}
// 添加观察者
public void addListener(ButtonListener listener) {
this.buttonListeners.add(listener);
}
}

事件

事件中包含事件源,即发出事件的对象,观察者需要这个源对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class ActionEvent {
long when;
Object source;
public ActionEvent(long when, Object source) {
this.when = when;
this.source = source;
}
public long getWhen() {
return this.when;
}
public Object getSource() {
return this.source;
}
}

观察者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface ButtonListener {
public void actionPerformed(ActionEvent e);
}
class ButtonPressListener1 implements ButtonListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("ButtonListener1 at " + e.when + ", do something...");
}
}
class ButtonPressListener2 implements ButtonListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("ButtonListener2 at " + e.when + ", do something too...");
}
}

执行

1
2
3
4
5
6
public static void main(String[] args) {
Button b = new Button();
b.addListener(new ButtonPressListener1());
b.addListener(new ButtonPressListener2());
b.buttonPress();
}

Composite 组合

Flyweight 享元

字符串常量池

Iterator 迭代器

容器的遍历

1
2
3
4
5
6
7
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}

Visitor 访问者

Builder 构建器

构建复杂对象:属性多,属性中还含有属性的对象

Adapter(Wrapper) 适配器

例:将 FileInputStream 转成 Reader,再交给 BufferedReader(Reader)

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("...");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String line = br.readLine();
while(line != null && !line.equals("")) {
System.out.println(line);
}
br.close();
}

Bridge 桥接

双维度扩展

情景:维度1:温和,凶猛,敏捷;维度2:狮子,老虎,小猫;如果将维度1和维度2组合,会出现9种情况,如果每种情况都写成一个类的话,类的个数会非常的多(类爆炸)

用聚合的方式将维度1包含维度2,使类的个数为n+m,而不是n*m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Main {
public static void main(String[] args) {
Animal cat = new CuteAnimal(new Cat());
Animal tiger = new ScaredAnimal(new Tiger());
}
}
abstract class Animal {
AnimalImpl impl;
}
class CuteAnimal extends Animal {
public CuteAnimal(AnimalImpl impl) {
this.impl = impl;
}
}
class ScaredAnimal extends Animal {
public ScaredAnimal(AnimalImpl impl) {
this.impl = impl;
}
}
class Cat extends AnimalImpl {}
class Tiger extends AnimalImpl {}
abstract class AnimalImpl {}

Command 命令

Memento 备忘录

记录快照,存盘恢复前状态

对象要实现标记接口:Serializable,即可以序列化和反序列化,将对象的状态存入文件,可从文件中读取恢复对象的状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public static void save() {
Person p = new Person(1, "zjm");
Location l = new Location("2", "3");
File f = new File("H:\\study\\person.data");
ObjectOutputStream oos = null;
try {
if (!f.exists())
f.createNewFile();
oos = new ObjectOutputStream(new FileOutputStream(f));
oos.writeObject(p);
oos.writeObject(l);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void load() {
File f = new File("H:\\study\\person.data");
ObjectInputStream oos = null;
try {
oos = new ObjectInputStream(new FileInputStream(f));
Person p = (Person) oos.readObject();
Location l = (Location) oos.readObject();
System.out.println(p);
System.out.println(l);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
class Person implements Serializable {
private int id;
private String name;
//...
}
class Location implements Serializable {
private String x;
private String y;
//...
}

Template Method 模板方法

父类中有一个函数是处理某一流程,这个流程在不同子类中在特殊环节上有区别,将不同的定义一个函数,让子类去重写这个函数,而不同重写整个流程的函数

Intepreter 解释器

您的支持鼓励我继续创作!