策略模式 [Strategy Pattern]
- 定义一个三个锦囊妙计的策略接口
- 分别实现三个妙计:
1)找乔国老帮忙,让吴国太给孙权施加压力
2)求吴国太开个绿灯,放行!
3)孙夫人断后,挡住追兵 - 定义一个存放妙计的锦囊
- 赵云使用三个妙计
策略模式的好处就是:
- 高内聚低耦合
- 扩展性:策略类可以继续增加下去,只需要修改Context.java即可
代理模式 [Proxy Pattern]
代理模式主要使用了 Java 的多态,干活的是被代理类,代理类主要是接活。怎么知道被代理类能不能干呢?大家知根知底,你能做啥,我能做啥都清楚的很,同一个接口呗。
- 定义一类女人,可以抛媚眼和陪酒。
- 潘金莲、贾氏均继承这类女人,完成相关的抛媚眼和陪酒活动。
- 定义王婆,指定完成抛媚眼和陪酒活动的对象。
- 定义西门庆,叫出王婆,王婆派人出来进行活动。
单例模式 [Singleton Pattern]
中国历史一般都是一朝代一个皇帝。只要大家提到皇帝,就知道指的是谁,清晰明确。问题是如果一个朝代有两个皇帝怎么办?就会产生错乱情况!所以需要用到单例模式。
- 定义一个皇帝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class Emperor {
private static Emperor emperor = null; // 定义一个皇帝,然后给他名字
public Emperor() {
}
// 获取实例
public static Emperor getInstance() {
if (emperor == null) { // 如果皇帝还没有定义,就定义一个
emperor = new Emperor();
}
return emperor;
}
// 皇帝叫什么?
public static void emperorInfo() {
System.out.println("我就是皇帝某某某....");
}
} - 定义大臣。大臣每天见皇帝,今天、昨天、前天皇帝不可以不一样!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17"all") // 告诉它对被批注的代码元素内部的某些警告保持静默 (
public class Minister {
/**
* @param args
*/
public static void main(String[] args) {
// 第一天
Emperor emperor1 = Emperor.getInstance();
emperor1.emperorInfo(); // 第一天的皇帝叫什么名字?
// 第二天
Emperor emperor2 = Emperor.getInstance();
emperor2.emperorInfo(); // 第二天的皇帝叫什么名字?
// 第三天
Emperor emperor3 = Emperor.getInstance();
emperor3.emperorInfo(); // 第三天的皇帝叫什么名字?
}
}
单例模式就是在构造函数中多加了一个构造函数,访问权限是private就可以了。
简单但有风险:
- 例如两个线程A,B,A正在执行new申请内存分配,可能需要0.001微秒,B执行到this.singletonPatton == null,这时候判断条件是true还是false?
- 如果是true,那么内存中不就存在了两个SingletonPattern的实例?
- 如果这个单例是创建一个信资源,就会出现业务逻辑混乱!
1
2
3
4
5
6
7
8
9
10
11
12public class SingletonPattern {
private static SingletonPattern singletonPattern = null;
// 限制住不能直接产生一个实例
private SingletonPattern() {}
// 获取实例
public SingletonPattern getInstance() {
if (this.singletonPattern == null) { //如果还没有实例,则创建一个
this.singletonPattern = new SingletonPattern();
}
return this.singletonPattern;
}
}
多例模式 [Multition Pattern]
特殊情况下,还是会有两个皇帝的朝代。这种场景放到我们设计模式中就叫有上限的多例模式。
- 先把几个皇帝定义出来。其中获取皇帝的实例:
1
2
3
4
5public static Emperor getInstance(){
Random random = new Random();
countNumOfEmperor = random.nextInt(maxNumOfEmperor); //随机拉出一个皇帝,
只要是个精神领袖就成
return (Emperor)emperorList.get(countNumOfEmperor); - 定义大臣。大臣是比较悲惨了,两个皇帝呀,怎么拜呀,不管了,只要是个皇帝就成。如果有的大臣有骨气只拜一个皇帝怎么处理?getInstance(param)就解决了这个问题!
1
2
3
4
5
6
7
8
9
10public static void main(String[] args) {
int ministerNum =10; //10个大臣
for(int i=0;i<ministerNum;i++){
Emperor emperor = Emperor.getInstance();
System.out.print("第"+(i+1)+"个大臣参拜的是:");
emperor.emperorInfo();
}
}
工厂方法模式 [Factory Method Pattern]
女娲造人
- 定义HumanFactory类,里面有
createHuman(Class c)
产生人类。 - 定义NvWa类,里面定义主方法,调用createHuman(WhiteHuman.class),createHuman(BlackHuman.class),createHuman(YellowHuman.class),并进行对应的笑、哭、讲话的行为。
但是这样创建太累了,那怎么办?神仙就想了:我塞进去一团泥巴,随机出来一群人,管他是黑人、白人、黄人,只要是人就成。
- 修改HumanFactory类,里面增加
createHuman()
,首先将三种人类放到List中,利用Random产生随机数,随机获取人种传入 createHuman(Class c)
产生人类。 - 修改NvWa类,只要调用
createHuman()
和相关行为操作即可。 - 增加一个ClassUtils类,定义
List<Class> getAllClassByInterface(Class c)
方法实现:给一个接口,返回这个接口的所有实现类。
好处:
- 增加了
createHuman()
后,这个工厂的扩展性更好了。以后要再加一个人类,只要你继续集成 Human 接口成了。 - 工厂模式还有一个非常重要的应用,就是延迟化。这个在类初始化很消耗资源的情况比较实用,通过这种方式可以很好的减少项目的复杂程度。
在HumanFactory类中定义一个MAP,初始化过的Human对象都放在这里。如果MAP中有,则直接从取出,不用初始化了。
延迟化:一个对象初始化完毕后就不释放,等到再次用到得就不用再次初始化了,直接从内存过中拿到就可以了。
抽象工厂模式 [Abstract Factory Pattern]
工厂方法模式中,女娲造人忘记给人类定义性别了,那怎么办?抹掉重来,然后就把人类重新洗牌,准备重新开始制造人类。
- 首先根据Huamn接口,完成抽象工厂模式下的产品等级和产品族,也就是定义人类以及产生出的人类是什么样子的。包括抽象黄种人、抽象白种人、抽象黑种人,以及实现类的黄种女人、黄种男人……
- 枚举出世界上有哪些类型的人。
- 创建工厂类。创建enum类型把世界上所有人类型都定义出来。定义一个HumanFactory接口,底下定义两个抽象类,分别创建男人和女人的”八卦炉”。
- 女娲开始造人。
好处:
- 高内聚,低耦合。
- 工厂模式符合 OCP 原则,也就是开闭原则。比如就性别的问题,这个世界上还存在双性人,那这个就是要在我们的产品族中增加一类产品,同时再增加一个工厂就可以解决这个问题。