《设计模式之禅》

代码见Github-Design-Patterns

策略模式 [Strategy Pattern]

  1. 定义一个三个锦囊妙计的策略接口
  2. 分别实现三个妙计:
    1)找乔国老帮忙,让吴国太给孙权施加压力
    2)求吴国太开个绿灯,放行!
    3)孙夫人断后,挡住追兵
  3. 定义一个存放妙计的锦囊
  4. 赵云使用三个妙计

策略模式的好处就是:

  1. 高内聚低耦合
  2. 扩展性:策略类可以继续增加下去,只需要修改Context.java即可

代理模式 [Proxy Pattern]

代理模式主要使用了 Java 的多态,干活的是被代理类代理类主要是接活。怎么知道被代理类能不能干呢?大家知根知底,你能做啥,我能做啥都清楚的很,同一个接口呗

  1. 定义一类女人,可以抛媚眼和陪酒。
  2. 潘金莲、贾氏均继承这类女人,完成相关的抛媚眼和陪酒活动。
  3. 定义王婆,指定完成抛媚眼和陪酒活动的对象。
  4. 定义西门庆,叫出王婆,王婆派人出来进行活动。

单例模式 [Singleton Pattern]

中国历史一般都是一朝代一个皇帝。只要大家提到皇帝,就知道指的是谁,清晰明确。问题是如果一个朝代有两个皇帝怎么办?就会产生错乱情况!所以需要用到单例模式

  1. 定义一个皇帝
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public 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("我就是皇帝某某某....");
    }
    }
  2. 定义大臣。大臣每天见皇帝,今天、昨天、前天皇帝不可以不一样!
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @SuppressWarnings("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
    12
    public 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. 先把几个皇帝定义出来。其中获取皇帝的实例:
    1
    2
    3
    4
    5
    public static Emperor getInstance(){ 
    Random random = new Random();
    countNumOfEmperor = random.nextInt(maxNumOfEmperor); //随机拉出一个皇帝,
    只要是个精神领袖就成
    return (Emperor)emperorList.get(countNumOfEmperor);
  2. 定义大臣。大臣是比较悲惨了,两个皇帝呀,怎么拜呀,不管了,只要是个皇帝就成。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public 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();
    }
    }
    如果有的大臣有骨气只拜一个皇帝怎么处理?getInstance(param)就解决了这个问题!

工厂方法模式 [Factory Method Pattern]

女娲造人

  1. 定义HumanFactory类,里面有createHuman(Class c)产生人类。
  2. 定义NvWa类,里面定义主方法,调用createHuman(WhiteHuman.class),createHuman(BlackHuman.class),createHuman(YellowHuman.class),并进行对应的笑、哭、讲话的行为。

但是这样创建太累了,那怎么办?神仙就想了:我塞进去一团泥巴,随机出来一群人,管他是黑人、白人、黄人,只要是人就成。

  1. 修改HumanFactory类,里面增加createHuman(),首先将三种人类放到List中,利用Random产生随机数,随机获取人种传入createHuman(Class c)产生人类。
  2. 修改NvWa类,只要调用createHuman()和相关行为操作即可。
  3. 增加一个ClassUtils类,定义List<Class> getAllClassByInterface(Class c)方法实现:给一个接口,返回这个接口的所有实现类。

好处:

  1. 增加了createHuman()后,这个工厂的扩展性更好了。以后要再加一个人类,只要你继续集成 Human 接口成了。
  2. 工厂模式还有一个非常重要的应用,就是延迟化。这个在类初始化很消耗资源的情况比较实用,通过这种方式可以很好的减少项目的复杂程度。
    在HumanFactory类中定义一个MAP,初始化过的Human对象都放在这里。如果MAP中有,则直接从取出,不用初始化了。

延迟化:一个对象初始化完毕后就不释放,等到再次用到得就不用再次初始化了,直接从内存过中拿到就可以了。

抽象工厂模式 [Abstract Factory Pattern]

工厂方法模式中,女娲造人忘记给人类定义性别了,那怎么办?抹掉重来,然后就把人类重新洗牌,准备重新开始制造人类。

  1. 首先根据Huamn接口,完成抽象工厂模式下的产品等级和产品族,也就是定义人类以及产生出的人类是什么样子的。包括抽象黄种人、抽象白种人、抽象黑种人,以及实现类的黄种女人、黄种男人……
  2. 枚举出世界上有哪些类型的人。
  3. 创建工厂类。创建enum类型把世界上所有人类型都定义出来。定义一个HumanFactory接口,底下定义两个抽象类,分别创建男人和女人的”八卦炉”。
  4. 女娲开始造人。

好处

  1. 高内聚,低耦合。
  2. 工厂模式符合 OCP 原则,也就是开闭原则。比如就性别的问题,这个世界上还存在双性人,那这个就是要在我们的产品族中增加一类产品,同时再增加一个工厂就可以解决这个问题。