0%

设计模式(补充)

2017年7月5日 下午2:38

2019年3月29日 下午2:04 复习

三种分类

创建型:创建类和对象
结构模式:有利于在原先的程序基础上进行改进
行为模式:模拟人类世界的各种复杂的关系

六个原则

一天一个设计模式—分类与六大原则 - Devil的技术小屋 - 博客频道 - CSDN.NET

  1. 开闭原则:
    1. 对扩展开放,对修改关闭
    2. 为了达到这样的效果,我们需要使用接口和抽象类
  2. 里氏代换原则:LSP
  3. 依赖倒转:
    1. 针对接口编程,依赖于抽象不依赖于具体
  4. 接口隔离原则:
    1. 使用多个隔离的接口,比使用单个接口要好。还可以降低类之间的耦合度的意思
  5. 吉米特法则:(最少知道原则)
    1. 一个实体应当尽量减少和其他实体放生相互作用
  6. 合成复用原则:
    1. 使用合成/聚合模式

单例模式:

  1. 一个类有且仅有一个实例,并且自行实例化向整个系统提供
  2. 多线程不能访问

两种写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
* 懒汉式
* @author czh
*
*/
public class SingleClass {
private static SingleClass single = null;
//私有构造方法
private SingleClass(){

}
//静态方法生成对象
public static SingleClass getInstance(){
if(single == null){
single = new SingleClass();
}
return single;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* 饿汉式
* @author czh
*
*/
public class SingleClass {
//这里直接声明对象
private static SingleClass single = new SingleClass();
//私有构造方法
private SingleClass(){

}
//静态方法生成对象
public static SingleClass getInstance(){
return single;
}

}

代理模式

使用场景:
1. 修改原有的的方法来适应。这样违反了“开闭”原则
2. 就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。
3. 估计将来要对方法进行改写,那么就提前使用代理模式
4. 用接口的原因
1. 为了保证方法的相同,方便客户端更方便的切换到代理类中
5. 与装饰模式的区别
1. 装饰类是对的扩展
2. 代理模式是对方法的扩展

图1 代理模式
代码在后

适配器模式

1. 主要分为三类:
    1. 类的适配器模式、
    2. 对象的适配器模式、
    3. 接口的适配器模式。
2. **对类的扩充**:当一个类需要满足是一个新的接口
3. **对对象的扩充**:当一个对象需要满足一个新的接口
4. **对接口的缩小**:当一个类需要满足部分当前接口的方法


图2 对类的扩充
注:
1. 这里是继承。
2. method1()继承自Source,method2()继承与Targetble接口
3. Adapter继承来的method1(),可以充当接口中的method1()

注:
1. 这里是依赖。
2. adapter中的Method1()调用source的method1()

注:
1. 这里是有一个抽象类Wrapper,起一个过滤作用

代码在后

几个问题

为啥组合优于继承

  1. 首先要确认,组合可以完成继承的任务
  2. 但是组合可以通过包含多个对象扩充自己的功能
  3. 而继承,只能获得父类的功能,要想扩充得自己写

怎样面向接口编程

  1. 接口可以理解成规则
  2. 一个公司有了规则,大家才能按一致的目标前进
  3. 试想没有规则,按大家的默契,也可以完成同样的目的
  4. 但是,默契容易忘,公司有了新的员工,或者我离开公司久了(我代码好久没有看了)
  5. 那么我一看规则(接口),那么就可以很快的学会。

站在扩充的角度去分类设计模式

  1. 适配器模式+代理模式+装饰模式
  2. 这三种都是可以在代码本身的基础进行扩充的
  3. 所以:当当前代码需要扩种的时候要从这三种里选

注:其他模式的分类,我依然是按上一篇文章给开头的分类表分的,网上的好多分类方法我现在还理解不了,只能按自己的来了。

代码

代理模式

Proxy.java

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
package package4;

public class Proxy implements Sourceable{
private Source source;

public Proxy(Source source) {
super();
this.source = source;
}

@Override
public void method() {
before();
source.method();
after();
}

public void before(){
System.out.println("前面的准备");
}

public void after(){
System.out.println("后面的处理");
}

}

Source.java

1
2
3
4
5
6
7
8
9
10
11
package package4;

public class Source implements Sourceable{

@Override
public void method() {
// TODO Auto-generated method stub
System.out.println("Source 的方法执行");
}

}

Sourceable.java

1
2
3
4
5
package package4;

public interface Sourceable {
void method();
}

适配器模式

  1. 对类的扩充+对对象的扩充
    Source.java(adapt1.java+adapt2.java公用)
    1
    2
    3
    4
    5
    6
    7
    package package5;
    //原类
    public class Source {
    public void method1(){
    System.out.println("method1");
    }
    }
    TargetInterface.java(adapt1.java+adapt2.java公用)
    1
    2
    3
    4
    5
    6
    package package5;

    public interface TargetInterface {
    void method1();
    void mehtod2();
    }

Adapt1.java:

1
2
3
4
5
6
7
8
9
10
11
package package5;

public class Adapt1 extends Source implements TargetInterface {

@Override
public void mehtod2() {
// TODO Auto-generated method stub
System.out.println("method2");
}

}

Adapt2.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package package5;
//第二种适配器
public class Adapt2 implements TargetInterface {
private Source source;

public Adapt2(Source source) {
super();
source = source;
}

@Override
public void mehtod2() {
// TODO Auto-generated method stub

}

@Override
public void method1() {
source.method1();

}
}

}

2019年3月29日 下午2:02 添加

  1. 模式1和模式2最大的不同在于adapt2.java有:

    1. private Source Source;//这句是最大的不同
  2. 但是目的是相同是:用新建的adapt类来代替原先的soures原始类,给source类添加一个method2()的方法。

    1. 注意:已经写死的类source本身不论如何都无法添加method2()了,我们只能让他的适配器adapt去实现这个愿望了
  3. 对接口方法的过滤
    代码顺序按照UML图
    SourceInterface.java

    1
    2
    3
    4
    5
    6
    7
    package package5;

    public interface SourceInterface {
    void method1();
    void method2();
    void method3();
    }

    AbstractSource.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package package5;

    public abstract class AbstractSource implements SourceInterface {

    @Override
    public void method1() {
    System.out.println("method1");

    }

    @Override
    public void method2() {
    System.out.println("method2");

    }

    @Override
    public void method3() {
    System.out.println("method3");
    }

    }

    Source1.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package package5;
    /*
    * 我需要那个方法,我就实现那个方法
    * 原来直接implement接口,三个方法我必须都实现。
    */
    public class Source1 extends AbstractSource {

    @Override
    public void method1(){
    System.out.println("改写method1方法");
    }
    }