[TOC]


设计模式概述

设计模式目的

    • 代码重用性
    • 可读性
    • 可靠性
    • 是程序具有低耦合性,高内聚性
    • 单一职责原则
    • 接口隔离原则
    • 依赖倒转原则(面向接口编程)
    • 里氏替换原则
    • 开闭原则
    • 迪米特法则
    • 合成复用原则

七大原则

单一职责原则

    • 降低类的复杂度,一个类只负责一个职责
    • 提高类的可读性,可维护性
    • 降低变更引起的风险
    • 通常情况下需要遵守单一职责的原则,但在类的方法特别少的情况下可以不遵守单一职责
    • 对于if...else语句需要谨慎使用,if...else使得代码的耦合程度太高,在必须使用if...else...时考虑使用构造方法或构造类的形式来代替if...else

接口隔离原则

    • 客户端不应该依赖不需要的接口,即一个类对另一个类的依赖需要建立在最小耦合的接口之上

依赖倒转原则(面向接口编程)

    • 高层模块不应该依赖于低层模块,二者都应该依赖于其抽象
    • 抽象不应该依赖细节,细节应该依赖于抽象
    • 依赖倒转即面向接口编程
    • 底层模块尽量有抽象类或接口或两者都有,这样使得程序的稳定性更好
    • 变量的声明类型尽量是抽象类或接口,这样使得变量引用和实际对象间有一层缓冲层,有利于程序的扩展和优化
    • 继承时遵循里氏替换原则

里氏替换原则

  • 如果对每个类型为T1的对象o1,有每个类型为T2的对象o2,若将程序所有为o1的地方改为o2,则程序不发生改动,则T2时T1的子类。即引用基类的地方都能透明的使用子类

    • 在使用继承时子类尽量不要重写父类方法
    • 继承使两个类的耦合程度增强了,在适当的情况下可以通过聚合,组合,依赖来解决
    • 将原来的继承关系进行接触
    • 创建一个公共的Base类,最抽象的类,使原先具有继承关系的两个类都来继承这个类
    • 在其中一个类里(一般为当初的子类),创建(当初父类)变量
    • 使用该对象的方法

开闭原则

    • 对扩展(提供者)开放,对修改(使用者)封闭。用抽象扩展框架,用实现修改细节
    • 当软件的需求发生变化时尽量通过软件的实体行为来发生变化,而不是通过修改已有的代码来实现
    • 编程中遵循的其他原则,以及设计模式的目的就是遵循开闭原则
    • 通过实现接口和抽象类来将实体进行抽离
    • 在实现的接口的子类或实现抽象类的子类中进行细节化,从而降低了耦合性

迪米特法则

    • 一个类应对其他类保持最小的了解

    • 类与类之间的关系越密切,其耦合度越大

    • 迪米特法则:

      即最少知到原则,一个类对自己依赖的类知到越少越好。也就是说,不管被依赖的类有多复杂,都尽量封装自己类内部,对外只提供public方法接口

      • 直接朋友:在类 的内部直接调用、声明、使用的类
      • 简介朋友:在方法的内部声明的局部变量(此时违反了迪米特法则)
    • 即设计需要按照一定的拓扑关系,不能越级调用,需要按照流程来执行想要的功能
    • 迪米特法则只要求降低耦合而不是完全没有耦合

合成复用原则

    • 找出可能变化之处,并将其独立出来
    • 针对接口编程,而不是针对实现编程
    • 为了交互对象而实现松耦合

UML类图

    • 依赖:

      只要是在类中用到了对方就存在依赖关系(最基本的类之间的关系,如果没有这个类,连编译都通过不了)

    • 泛化(继承):

      依赖关系的特例

    • 实现:

      实现接口,实现关系也为依赖关系

    • 关联:

      1. 表示类与类之间的特例也为依赖关系
      2. 关联具有导航性,即一对一或是一对多

      一对一:

      1
      2
      3
      4
      5

      classDiagram
      class Person{
      IDCard card;
      }

      双向一对一:

      1
      2
      3
      4
      5
      6
      7
      8
      classDiagram
      class Person{
      IDCard card;
      }

      class IDCard{
      Person person;
      }
    • 聚合:

      ​ 各部分成员之间可以分离,既可以独立存在

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      classDiagram
      Computer <|-- Keyboard
      Computer <|-- Mouse

      class Computer{
      Mouse mouse;
      Keyboard board;
      }

      class Keyboard{

      }

      class Mouse{

      }

    • 组合:

      ​ 各部分成员之间不可以分离,即不可以独立存在,必须共生共灭

      1
      2
      3
      4
      5
      6
      classDiagram
      class People{
      Head head = new Head();
      Nose nose = new Nose();

      }

设计模式

基本概念

    1. 创建型模式
      • 单例模式
      • 抽象工厂模式
      • 原型模式
      • 建造者模式
      • 工厂模式
    2. 结构型模式
      • 适配器模式
      • 桥接模式
      • 装饰模式
      • 组合模式
      • 外观模式
      • 享元模式
      • 代理模式
    3. 行为型模式
      • 模板方法模式
      • 命令模式
      • 访问者模式
      • 迭代器模式
      • 观察者模式
      • 中介者模式
      • 备忘录模式
      • 解释器模式
      • 状态模式
      • 策略模式
      • 职责链模式

单例模式

饿汉式
  1. 静态常量写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Hungry1{
    // 隐藏构造器,使得类外无法创建对象
    private Hungry1() {

    }
    // 创建静态对象
    static final private Hungry1 h1 = new Hungry1();

    // 提供静态对象接口
    static Hungry1 getHungrt() {
    return h1;
    }
    }

  2. 静态代码块写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class Hungry1{
    private Hungry1() {

    }

    static final private Hungry1 h1;

    static {
    h1 = new Hungry1();
    }


    static Hungry1 getHungrt() {
    return h1;
    }
    }

懒汉式
  1. 线程不安全方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Hungry2{
    private Hungry2() {

    }

    static private Hungry2 h2;

    static Hungry2 getHungry() {
    if(h2 == null) {
    h2 = new Hungry2();
    return h2;
    }
    else return h2;
    }
    }

    • 1
      2
      3
      4
      if(h2 == null) {
      h2 = new Hungry2();
      return h2;
      }

      语句,所以存在线程安全问题,不可以在多线程并发的执行(除非专门控制并发)


2. 线程安全式(同步方法方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Hungry2{
private Hungry2() {

}

static private Hungry2 h2;

public static synchronized Hungry2 getHungry() {
if(h2 == null) {
h2 = new Hungry2();
return h2;
}
else return h2;
}
}
// 添加syn关键字,保证线程安全

  1. 线程安全式(同步代码块形式)

    错误方式,不存在!!!!

双重检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Hungry3{

private Hungry3() {

}

static private volatile Hungry3 h3;

public static Hungry3 getInstance() {
if(h3 == null) {
synchronized (Hungry3.class) {
if(h3 == null)h3 = new Hungry3();

}
}
return h3;
}
}

静态内部类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class StaticInnerClass {

@Test
public void test() {

}

}
class Static{
private Static() {

}


private static class StaticInner{
private static Static instance = new Static();
}

public static Static getInstance() {
return StaticInner.instance;
}
}

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

import org.junit.jupiter.api.Test;

public class EnumClass {
@Test
public void test() {
Enum e1 = Enum.Instance;
Enum e2 = Enum.Instance;
System.out.println(e1 == e2);
}

}
enum Enum{
Instance();

private Enum() {

}


}
单例模式注意
    • 需要频繁创建和销毁对象的场景

    • 创建对象耗时或耗费资源过多但又经常用到的对象

      若能确保单线程的情况下:饿汉式(静态常量、静态代码块)

      多线程情况下:双重检查,枚举类,静态内部类

工厂模式

简单工厂模式
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
classDiagram
class Pizza{
Attributes
}

class OrderPizza{
Factory factory;
}

class Factory{
Pizza getPizza()
}

class BJPizza{

}

class TJPizza{

}


Pizza <|-- TJPizza
Pizza <|-- BJPizza


Factory <| -- BJPizza
Factory <| -- TJPizza
OrderPizza <|-- Factory
Factory <|-- OrderPizza
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Factory.SimpleFactory;

public class Factory {

public Pizza getPizza(String name) {
Pizza pizza = null;
if(name.equals("BJ") || name.equals("TJ"))
pizza = new Pizza(name);

return pizza;

}

}

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
package Factory.SimpleFactory;

import org.junit.jupiter.api.Test;

public class OrderPizza {

private Factory factory = new Factory();
private Pizza pizza = null;


@Test
public void getPizza() {
String name = "BJ";

pizza = factory.getPizza(name);

if(pizza == null)
System.out.println("no");
else
System.out.println("yes");

}



}

1
2
3
4
5
6
7
8
9
10
11
package Factory.SimpleFactory;

public class Pizza {
public Pizza(String name) {
this.name = name;
}

String name;

}

    • 简单工厂模式为对于种类较少的多个同种基类的创建,使用一个类进行菜单的作用,利用菜单进行分发,使用工厂类进行创建
工厂方法模式
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
45
46
classDiagram
class Pizza{

}

class BJPepperPizza{

}

Pizza <|-- BJPepperPizza
BJPepperPizza <|-- BJOrder

class BJSourPizza{

}

Pizza <|-- BJSourPizza
BJSourPizza <|-- BJOrder
class TJPepperPizza{

}

Pizza <|-- TJPepperPizza
TJPepperPizza <|-- TJOrder
class TJSourPizza{

}

Pizza <|-- TJSourPizza
TJSourPizza <|-- TJOrder

class BJOrder{

}
BJOrder <|-- Order
class TJOrder{

}
TJOrder <|-- Order
class Order{

}




1
2
3
4
5
6
7
8
9
10
11
12
13
package Factory.FactoryMethods.Pizzas;

public class Pizza {

String name;
public Pizza(String name) {
this.name = name;
}

}



1
2
3
4
5
6
7
8
9
10
package Factory.FactoryMethods.Pizzas;

public class BJPizza extends Pizza{
public BJPizza(String name) {
// TODO Auto-generated constructor stub
super(name);
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package Factory.FactoryMethods.Orders;

import Factory.FactoryMethods.Pizzas.Pizza;
import Factory.FactoryMethods.Pizzas.TJPizza;

public class TJOrder extends Order{
@Override
Pizza getPizza(String name) {
// TODO Auto-generated method stub
Pizza pizza = null;

if(name.equals("22"))
pizza = new TJPizza(name);


return pizza;
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package Factory.FactoryMethods.Orders;

import Factory.FactoryMethods.Pizzas.Pizza;

public abstract class Order {

public Order() {
// TODO Auto-generated constructor stub
}

public void orderPizza(String name) {
Pizza pizza = getPizza(name);


}

abstract Pizza getPizza(String name);

}

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

import Factory.FactoryMethods.Pizzas.BJPizza;
import Factory.FactoryMethods.Pizzas.Pizza;

public class BJorder extends Order{
@Override
Pizza getPizza(String name) {
// TODO Auto-generated method stub
Pizza pizza = null;
if(name.equals("ll"))
pizza = new BJPizza(name);

return pizza;



}


}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package Factory.FactoryMethods.Orders;

import Factory.FactoryMethods.Pizzas.Pizza;
import Factory.FactoryMethods.Pizzas.TJPizza;

public class TJOrder extends Order{
@Override
Pizza getPizza(String name) {
// TODO Auto-generated method stub
Pizza pizza = null;

if(name.equals("22"))
pizza = new TJPizza(name);


return pizza;
}

}

抽象工厂模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
classDiagram
Pizza <|-- BJPepperPizza
Pizza <|-- TJPepperPizza

Pizza <|-- BJSourPizza
Pizza <|-- TJSourPizza

BJPepperPizza <|-- Order
TJPepperPizza <|-- Order
BJSourPizza <|-- Order
TJSourPizza <|-- Order

Order <|-- BJFactory
Order <|-- TJFactory
BJFactory <|-- AbsFactory
TJFactory <|-- AbsFactory




1
2
3
4
5
6
7
8
9
10
11
12
13
14
package Factory.Abstract;

public class Order {
AbsFactory factory;

public void setFactory(AbsFactory factory,String name) {
this.factory = factory;

Pizza pizza = factory.getPizza(name);

}

}

1
2
3
4
5
6
7
8
package Factory.Abstract;

public interface AbsFactory {

public Pizza getPizza(String name);

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Factory.Abstract;

public class BJFactory implements AbsFactory{


@Override
public Pizza getPizza(String name) {
// TODO Auto-generated method stub
Pizza pizza = null;

if(name.equals("6"))
pizza = new BJPizza(name);

return pizza;
}
}

1
2
3
4
5
6
7
8
package Factory.Abstract;

public class TJPizza extends Pizza{
TJPizza(String name){
super(name);
}
}

原型模式

建造者模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
classDiagram
class HosueBuilder
class CommonHouse
class HighHouse

HosueBuilder <|-- CommonHouse
HosueBuilder <|-- HighHouse

class House
class Director
Director : 【中间商】


Director <|-- HosueBuilder
House <|-- Director



HosueBuilder : void buildBasic()
HosueBuilder : void buildWalls()
HosueBuilder : void roofed()

    • Product:一个具体的产品对象
    • Builder:抽象的建造者(接口或者抽象类)
    • ConcreateBuilder:具体的建造者
    • Director:指挥者,构建一个使用Builder接口的对象。它主要是用于创建一个很复杂的对象,拥有两个作用:
      1. 隔离客户和产品的生产过程
      2. 负责控制产品对象的生产过程
1
2
3
4
5
6
7
8
9
10
11
12
13
package Builder;

public interface BuildeHouse {

House house = new House();

public void buildWalls();
public void buildBasic();
public void roofed();


}

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 Builder;

public class CommonHouse implements BuildeHouse{


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

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

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

}

}

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 Builder;

public class HighHouse implements BuildeHouse{

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

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

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

}

1
2
3
4
5
6
package Builder;

public class House {

}

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

public class Director {

BuildeHouse builder;

public Director(BuildeHouse builder) {
this.builder = builder;
}

public void setBuilder(BuildeHouse builder) {
this.builder = builder;
}

public void buildHouse() {
builder.buildBasic();
// builder.buildBasic();
builder.buildWalls();
builder.roofed();
}



}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package Builder;

import org.junit.jupiter.api.Test;

public class Client {

@Test
public void test() {
Director director = new Director(new CommonHouse());
director.setBuilder(new HighHouse());

director.buildHouse();


}

}

    • 客户端不需要知到内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
    • 每一个具体的建造者都相对独立,而与其他的具体建造者无关,因此可以很方便的替代具体建造者或增加新的具体建造者,用户使用不同的具体建造者得到不同的产品对象
    • 可以更加精细的控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
    • 增加具体的建造者无需修改原有的代码,满足了OOP原则
    • 建造者模式需要具体的实现类步骤相差不大,若步骤相差很大则不适合使用建造者模式
    • 若产品内部变化复杂,则需要定义许多具体的建造者来适应这种变化,会使得系统变得庞大,需要考虑是否继续使用建造者模式
  • 抽象工厂模式实现对产品家族的创建,即不需要关系产品生产的步骤,只需要将生产的产品交给指定的工程工厂进行生产即可,至于生产步骤需要具体的工厂自己指定,而建造者模式对具体产品的生产步骤已经确定,而各个具体的建造者需要按照相同的模块,但至于模块的细节需要各个具体建造者自己实现

1
2
3
4
5
6
7
8
classDiagram
class MidFactory
MidFactory : abstractBuild

class MidBuilder
MidBuilder : buildConcreate1
MidBuilder : buildConcreate2
MidBuilder : buildConcreate3

适配器模式

1
2
3
4
5
6
7
8
9
10
classDiagram
class Voltage220V
class Voltage5V
class AdapterVoltage
class Phone


AdapterVoltage <|-- Voltage220V
AdapterVoltage <|-- Voltage5V
Phone <|-- AdapterVoltage
    1. 三种适配方式是以src如何给到adapter来命名的
      • 类适配器:以类给到,在Adapter里,就是将src当作类,继承(泛化)
      • 对象适配器:以对象给到,在adapter里,将src作为一个对象属性,持有(聚合)
      • 接口适配器:以实现接口的形式,使adapter实现src的方法(实现)
    2. Adapter模式最大的作用是将原本不兼容的接口融合在一起工作
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package Adapter;

    public class Voltage220V {

    public int outPut220V() {
    return 220;
    }

    }

    1
    2
    3
    4
    5
    6
    7
    8
    package Adapter;

    public interface Voltage5V {

    public int outPut5V();

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package Adapter;

    public class VoltageAdapter extends Voltage220V implements Voltage5V{


    @Override
    public int outPut5V() {
    // TODO Auto-generated method stub
    int input = outPut220V();
    return (input / 44);

    }


    }

    • 由于java的单继承机制,所以要求dst只能为接口,有一定的局限性
    • 由于继承了src,使得src的方法暴露出来,增加了adapter的成本
    • 继承来src,便于更灵活的重写Src的方法
对象适配器
1
2
3
4
5
6
7
8
9
10
classDiagram
class Voltage220V
class Voltage5V
class AdapterVoltage
class Phone

AdapterVoltage : Voltage220V voltage
AdapterVoltage <|-- Voltage220V
AdapterVoltage <|-- Voltage5V
Phone <|-- AdapterVoltage
    • 基本思路与类适配器相同,但是不是继承Src,而是通过聚合的方式持有src类,进而实现dst接口,从而完成src -> dst的转变
    • 符合合成复用原则,用关联的方式替代继承的方式
接口适配器(缺省适配器模式)
    • 只使用一个接口中的个别函数,可以通过构建一个抽象类空实现接口的函数,再构建该抽象函数的子类,重写指定的函数,完成接口的适配
    • 适用于一个接口不想使用其全部方法的场景

桥接模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classDiagram
class Phone
class VIVO
class XiaoMi


class Brand
class FolderPhone

Brand : void open()
Brand : void close()

VIVO <|-- Brand
XiaoMi <|-- Brand
Phone <|-- VIVO
Phone <|-- XiaoMi
FolderPhone <|-- Phone
    • 将实现和抽象放在两个不同的层次,使两个层次可以独立的改变

    • 是一种结构型设计模式

    • Bridge模式基于类的最小的设计原则

    • 各成分:

      1. Client:桥接模式的调用者

      2. Abstraction:维护了实现层的接口,二者是聚合关系

      3. RefinedAbstraction:接口的具体实现类

1
2
3
4
5
6
7
8
9
package Bridge;

public interface Brand {

void open();
void close();

}

1
2
3
4
5
6
7
package Bridge;

public class FolderPhone extends Phone{


}

1
2
3
4
5
6
7
8
package Bridge;

public abstract class Phone {

Brand brand;

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Bridge;

public class Vivo implements Brand{

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

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

}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package Bridge;

public class XiaoMi implements Brand{
@Override
public void close() {
// TODO Auto-generated method stub

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

}

}

    • 实现了抽象和实现部分的分离。从而提高了系统的灵活性,让抽象部分和实现部分分离开,有助于系统的分层设计,从而产生更好的系统结构
    • 对于系统的高层部分,只需要知道系统的实现部分和抽象部分的接口就可以,其他部分由业务来实现
    • 桥接模式代替多层继承方案,可以减少子类的个数,降低系统的管理和维护成本
    • 桥接模式的引入增加了系统的理解和设计难度,桥接模式要求将抽象部分和实现部分分离出,有一定的局限性

装饰者模式

以io模块为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
classDiagram
class InputStream

class FileInputStream
class StringBufferInputStream
class ByteArrayInputStream
class FilterInputStream

InputStream <|-- FileInputStream
InputStream <|-- StringBufferInputStream
InputStream <|-- ByteArrayInputStream
InputStream <|-- FilterInputStream

class BufferInputStream
class DataInputStream
class LineNumberInputStream

FilterInputStream : InputStream is
FilterInputStream <|-- BufferInputStream
FilterInputStream <|-- DataInputStream
FilterInputStream <|-- LineNumberInputStream
    • FilterInputStream:装饰器
    • InputStream:抽象类
    • FileInputStream,StringBufferStrean,ByteArratInputStream:具体被修饰类
    • BufferInputStream,DataInputStream..:具体修饰类
1
2
3
4
5
6
7
8
9
10
11
12
package Decorate;

public class BlackCoffee extends Coffee{

@Override
int cost() {
// TODO Auto-generated method stub
return super.cost() + 10;
}

}

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

public class Coffee extends Drink{


@Override
int cost() {
// TODO Auto-generated method stub
return 5;
}
@Override
void setCost() {
// TODO Auto-generated method stub

}


}

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 Decorate;

public class Decorater extends Drink{

Drink drink;
@Override
int cost() {
// TODO Auto-generated method stub
int cost_temp = 0;
if(drink != null)
cost_temp = drink.cost();
return cost_temp + cost;
}

void setDrink(Drink drink) {
this.drink = drink;
}@Override
void setCost() {
// TODO Auto-generated method stub

}

}

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

public abstract class Drink {

int cost;
abstract int cost();
abstract void setCost();

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Decorate;

public class Sugar extends Decorater{

void getCost() {
int temp_cost = 0;
if(drink != null)
temp_cost = drink.cost();

cost = temp_cost + 5;

}

}

  • 在装饰者模式中,对于某类的修饰,将被修饰的部分和修饰部分进行抽象和分离,使修饰和被修饰的部分都继承一个公共的抽象类,从而便于在修饰类中添加被修饰的对象,使得可以多层嵌套进行修饰

外观模式(过程模式)

    1. 外观模式可以理解为转换一群接口,客户只要调用一个接口,而不调用多个接口才能达到目的
    2. 外观模式就是解决多个复杂接口带来的使用困难,起到简化用户操作的作用

享元模式

    • 享元模式也叫蝇量模式,运用共享技术有效的支持大量细粒度的对象
    • 常用于 系统底层的开发,解决系统性能问题。像数据库连接池,里面都是创建好的连接对象,在这些连接对象中有我们需要的则直接拿来使用,避免重复创建,如果没有需要的则创建一个
    • 享元模式能够解决重复对象的内存浪费问题,当系统中由大量的相似对象,需要缓冲池时不需要重复创建对象,可以从缓冲池中获得,这样可以降低系统内存,同时提高效率
    • 享元模式的经典应用即池技术
    • FlyWeight:抽象的享元角色,产品的抽象类,定义出对象的外部状态内部状态的接口或实现
    • ConcreteFlyWeigft:具体的享元角色,具体的产品类,实现角色定义的相关业务
    • UnsharedConcreteFlyWeight:不可共享的角色,不会出现在享元工厂中
    • FlyWeightFactory:享元工厂,用于构建一个容器池(set),同时构建从容器中获取对象的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classDiagram
class FlyWeight
class FlyWeightFactory
class ConcreteFlyWeight
class UnsharedConcreteFlyWeight
class Client


FlyWeight <|-- ConcreteFlyWeight
FlyWeight <|-- UnsharedConcreteFlyWeight
FlyWeight : void operate
FlyWeightFactory : void getFlyWeight

FlyWeightFactory <|-- FlyWeight
FlyWeightFactory <|-- Client
ConcreteFlyWeight <|-- Client
UnsharedConcreteFlyWeight <|-- Client
    • 内部状态:内部状态是对象共享出来的属性,不会随着环境的变化而变化
    • 外部状态:外部状态随着环境的改变而改变,是不可以共享的状态
1
2
3
4
5
6
package FlyWeight;

public abstract class WebSite {

}

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

public class ConcreteWebSite extends WebSite{
String type;
public ConcreteWebSite(String type) {
// TODO Auto-generated constructor stub
this.type = type;
}


}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package FlyWeight;

import java.util.HashMap;

public class WebSiteFactory {

private HashMap<String,ConcreteWebSite> pool = new HashMap<String, ConcreteWebSite>();

public WebSite getWebSite(String type) {
if(!pool.containsKey(type))
pool.put(type, new ConcreteWebSite(type));

return (WebSite)pool.get(type);
}

}

    • 享元模式,享即共享,元即对象
    • 享元模式注意内部和外部的划分,共享内部,细化外部
    • 使用享元模式需要一个工厂类进行控制

代理模式

静态代理
1
2
3
4
5
6
7
8
package Proxy;

public interface TeacherDao {

void teach();

}

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

public class TeacherDaoImpl implements TeacherDao{
@Override
public void teach() {
// TODO Auto-generated method stub
System.out.println("this is teacher");

}
}

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

public class TeacherProxy implements TeacherDao{

TeacherDao teacher;
public TeacherProxy(TeacherDao teacher) {
// TODO Auto-generated constructor stub
this.teacher = teacher;
}

@Override
public void teach() {
// TODO Auto-generated method stub
System.out.println("this proxy saying");
teacher.teach();

}


}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package Proxy;

import org.junit.jupiter.api.Test;

public class TestClass {

@Test
public void test() {
TeacherDao teacher = new TeacherProxy(new TeacherDaoImpl());
teacher.teach();
}

}

动态代理(JDK代理)
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
package Proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactory {

Object target;

public void setTarget(Object obj) {
this.target = obj;
}

public ProxyFactory(Object obj) {
target = obj;
}

public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler(
) {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy");
// TODO Auto-generated method stub
method.invoke(target, args);
return null;
}
});
}


}

参数说明:

newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler):

  • 参数一:被代理对象的类的加载器
  • 参数二:被代理对象类的接口集合
  • 参数三:事件处理,执行目标对象的方法时,会触发事件处理器的方法,进而完成代理方法的加强
动态代理(CGLIB代理)
    • 无论是静态代理,或是动态的JDK代理,都需要类实现一个或多个接口,当被代理对象未实现接口时,则不可以使用以上的两种代理方式
    • CGLIB代理也叫做子类代理,他是在内存中构建一个子类对象而实现对目标功能的拓展
    • CGLIB底层通过ASM字节码处理框架来转化成字节码文件
    • 引入相应的jar包
    • 在内存中动态的构建子类,注意代理类不能未final类
    • ,目标对象的方法若为 final / static则目标方法不会被拦截,即目标方法不会被增强
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
package Proxy.CGLIB;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ProxyFactory implements MethodInterceptor{

Object target;

public ProxyFactory(Object obj) {
// TODO Auto-generated constructor stub
this.target = obj;
}


public Object getProxyInstance() {

// 创建工具类
Enhancer enhancer = new Enhancer();

//设置父类
enhancer.setSuperclass(target.getClass());

//设置回调函数
enhancer.setCallback(this);

//创建子类对象,即代理对象
return enhancer.create();

}

@Override
public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("cglib代理方法");
method.invoke(target, arg2);
return null;
}
}

1
2
3
4
5
6
7
8
9
10
package Proxy.CGLIB;

public class TeacherDao {

void teach() {
System.out.println("被代理对象");
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Proxy.CGLIB;

import org.junit.jupiter.api.Test;

public class Client {

@Test
public void test() {
TeacherDao teacher = new TeacherDao();
TeacherDao proxy = (TeacherDao)new ProxyFactory(teacher).getProxyInstance();
System.out.println(proxy.getClass());
}

}

代理模式的变种

模板方法模式

    • 在一个抽象类中公开定义了执行它的方法的模板,它的子类可以按需要重写方法的实现,但调用将以抽象类中定义的方式执行
    • 模板方法模式是一个操作中算法的骨架,将一些步骤延迟到子类中实现,使得子类可以不改变一个算法的结构,就可以重写定义算法的某些特征
    • 模板方法模式属于行为型模式
    • AbstractClass:定义了抽象方法,和抽象方法的执行骨架
    • ConcreteClass:具体实现抽象的方法但是需要按照骨架进行顺序执行
基本模板方法模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package TemplateMethods;

public abstract class MakeDrink {


// 注意添加final关键词,防止子类重写该方法
final void operate() {
System.out.println("select:" + select() + " add: " + add());
}

abstract String select();
abstract String add();


}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package TemplateMethods;

public class RedDrink extends MakeDrink{
@Override
String add() {
// TODO Auto-generated method stub
return "red!!";
}
@Override
String select() {
// TODO Auto-generated method stub
return "select red!";
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package TemplateMethods;

import org.junit.jupiter.api.Test;

public class Client {
@Test
public void test() {

MakeDrink drink = new RedDrink();
drink.operate();
}

}

钩子方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package TemplateMethods;

public abstract class MakeDrink {

final void operate() {

if(isPure()) {
addEquip();
}
}

void addEquip() {
System.out.println("select:" + select() + " add: " + add());
}
abstract boolean isPure();
abstract String select();
abstract String add();


}

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 TemplateMethods;

public class PureDrink extends MakeDrink{
@Override
String add() {
// TODO Auto-generated method stub
return null;
}

@Override
boolean isPure() {
// TODO Auto-generated method stub
return true;
}


@Override
String select() {
// TODO Auto-generated method stub
return null;
}

}

命令模式

访问者模式

    • Visitor:抽象的visitor类,为子类提供visit方法
    • ConcreteVistior:visitor的具体实现类
    • Visited:被访问者的抽象类,为子类提供访问者的accpet接口
    • ConcreteVisited:被访问者的具体实现类,调用accept方法
1
2
3
4
5
6
7
8
9
10
11
12
package Visitors;

public class ObjectStructure {

Person persons[];


void setPerson() {

}
}

1
2
3
4
5
6
7
package Visitors;

public abstract class Action {
abstract void setAction();

}

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

public class Failed extends Action{
@Override
void setAction() {
// TODO Auto-generated method stub

}
}

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

public class Sucessfully extends Action{
@Override
void setAction() {
// TODO Auto-generated method stub

}
}

1
2
3
4
5
6
7
8
9
package Visitors;

public abstract class Person {
Action action;

abstract void accpet(Action action);

}

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

public class Man extends Person{
@Override
void accpet(Action action) {
// TODO Auto-generated method stub
this.action = action;
}
}

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

public class Woman extends Person{
@Override
void accpet(Action action) {
// TODO Auto-generated method stub
this.action = action;
}
}

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

public class ObjectStructure {

Person persons[];


void setPerson() {

}
}

双分派
  • 首先将一个对象作为参数传入(第一次分派)
  • 在被传入的方法中将this作为参数传入第一个对象的某个方法内
1
2
3
4
5
6
7
8
9
10
11
12
package Visitors.Doule;

public class A {
String name = "A";

public void getBMethods(B b) {
b.method(this);
}


}

1
2
3
4
5
6
7
8
9
10
package Visitors.Doule;

public class B {

public void method(A a) {
System.out.println(a.name);
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
package Visitors.Doule;

import org.junit.jupiter.api.Test;

public class TestClass {
@Test
public void test() {
A a = new A();
a.getBMethods(new B());
}

}

    • 优点:
      1. 访问者模式具有单一性职责原则,具有更好的可扩展性,灵活性高
      2. 访问者模式可以对功能进行统一,可以做报表,UI,拦截器和过滤器,使用与结构稳定的系统
    • 缺点:
      1. 具体元素需要对访问者公布细节,也就是访问者关注了类的其他细节
      2. 违反了依赖倒转原则,访问者依赖的是具体的元素而不是抽象的元素

迭代器模式

    • 迭代器模式常用的设计模式,属于行为模式
    • 如果集合元素是用不同方式实现的,,则客户端遍历这些元素时就需要使用不同的方式,可能还会暴露元素内部属性
    • 迭代器模式提供遍历元素的统一接口用一致的方法遍历元素,不需要知到集合元素的底层表示,即不爆露内部结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
classDiagram
class Iterator
Iterator : boolean hasNext
Iterator : E next
Iterator : void remove



class ConcreteIterator
ConcreteIterator <|-- Iterator


class Aggregate
Aggregate : void createIterator
class ConcreteAggregate
ConcreteAggregate <|-- Aggregate
ConcreteAggregate <|-- ConcreteIterator

ConcreteAggregate : ArrayList elements

    • Iterator:迭代器接口,系统提供,含有hasNext,next,remove
    • ConcreteIterator:具体的迭代类,管理迭代
    • Aggregate:一个统一的聚合接口,将客户端与聚合解耦
    • ConcreteAggregate:具体的聚合持有对象,并返回迭代器对象,遍历元素
    • Client:客户端,通过Iterator和Aggregate依赖子类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package Iterator;

import java.util.Iterator;
import java.util.List;

public interface College {


public Iterator getIterator();



}

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

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ComputerCollege implements College{

List<Department> list;

String name = "computer";

public ComputerCollege() {
// TODO Auto-generated constructor stub
list = new ArrayList<>();
list.add(new Department("66"));
list.add(new Department("77"));
}

@Override
public Iterator getIterator() {
// TODO Auto-generated method stub
return new ComputerIterator(list);
}

public String toString() {
return name;
}

}

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

import java.util.Iterator;
import java.util.List;

public class ComputerIterator implements Iterator{

List<Department> list;
int index = 0;

@Override
public boolean hasNext() {
// TODO Auto-generated method stub

if(index < list.size())return true;
return false;
}
@Override
public Object next() {
// TODO Auto-generated method stub
return list.get(index++);
// return null;
}
public ComputerIterator(List<Department> list) {
// TODO Auto-generated constructor stub
this.list = list;
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Iterator;

public class Department {
String name;
public Department(String name) {
// TODO Auto-generated constructor stub
this.name = name;

}
public String toString() {
return name;
}

}

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

import java.util.Iterator;
import java.util.List;

public class OutPutImpl {
List<College> list;
public OutPutImpl(List<College> list) {
// TODO Auto-generated constructor stub
this.list = list;
}

public void printCollege() {
Iterator<College> iterator = list.iterator();
while(iterator.hasNext()) {
College college = iterator.next();
System.out.println(college);
printDepartment(college.getIterator());

}
}

private void printDepartment(Iterator iterator) {
while(iterator.hasNext()) {
System.out.println(iterator.next());
}

}

}

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

import java.util.ArrayList;

import org.junit.jupiter.api.Test;

public class TestClass {

// @Test
// public void test() {
// Iterator<E>
//
// }
// 7
@Test
public void client() {
ArrayList<College> list = new ArrayList();
list.add(new ComputerCollege());

OutPutImpl impl = new OutPutImpl(list);
impl.printCollege();



}

}

    • 优点:
      1. 提供了一个统一遍历容器的方法,不需要考虑聚合的类型,使用一种方法就可以遍历对象
      2. 隐藏了聚合的内部的细节,客户端遍历时只能取到迭代器,而不知道迭代的具体组成
      3. 遵循了单一职责原则,将对象的管理和对象的遍历进行分开,使用内部类的迭代进行对象的迭代使用外部类的方法进行对象的管理
    • 缺点:每个聚合的对象都需要一组迭代器,多个类会有多个迭代器

观察者模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classDiagram
class Subject
Subject : registeObeserver
Subject : removeObserver
Subject : notifyObserver

class Data
Data : List<Observer> list
Data <|-- Subject
Data : setNewValue

class Observer
Observer : update
Observer : show

class CurrentCondition
CurrentCondition <|-- Observer
Data <|-- CurrentCondition

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

public interface Subject {

public void registObserver(Observer o);
public void removerObserver(Observer o);
public void notifyObserver();

}

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
45
46
47
package Observer;

import java.util.ArrayList;
import java.util.List;

public class WeatherData implements Subject{

List<Observer> list;
double value;


public WeatherData() {
// TODO Auto-generated constructor stub
list = new ArrayList();
}

@Override
public void notifyObserver() {
// TODO Auto-generated method stub
for(Observer o : list)
o.update(value);


}
@Override
public void registObserver(Observer o) {
// TODO Auto-generated method stub
if(!list.contains(o))
list.add(o);

}

@Override
public void removerObserver(Observer o) {
// TODO Auto-generated method stub
if(list.contains(o))
list.remove(o);

}

public void valueReset(double v) {
value = v;
notifyObserver();
}

}

1
2
3
4
5
6
7
8
package Observer;

public interface Observer {
public void update(double value);
public void show(double value);

}

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

public class CurrentCondition implements Observer{


@Override
public void update(double value) {
// TODO Auto-generated method stub
show(value);

}

@Override
public void show(double value) {
// TODO Auto-generated method stub
System.out.println("new value: " + value);

}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Observer;

public class BaiduObserver implements Observer{
@Override
public void show(double value) {
// TODO Auto-generated method stub
System.out.println("baidu: " + value);

}
@Override
public void update(double value) {
// TODO Auto-generated method stub
show(value);
}

}

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

import org.junit.jupiter.api.Test;

public class Client {

public static void main(String[] args) {
WeatherData data = new WeatherData();

CurrentCondition condition = new CurrentCondition();
data.registObserver(condition);
data.registObserver(new BaiduObserver());

data.valueReset(2);

//data.removerObserver();
}
}


中介者模式

    • 用一个中介对象来封装一系列的对象交互。中介者使其对象不需要显示的互相引用,从而使其耦合松散,而且可以独立的改变他们之间的交互
    • 中介者者模式属于行为型模式,使代码易于维护
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    classDiagram
    class Mediator
    class ConcreteMediator
    ConcreteMediator <|-- Mediator

    class Colleague
    class ConcreteColleague
    ConcreteColleague <|-- Colleague
    Mediator <|-- Colleague
    Mediator <|-- ConcreteColleague
    ConcreteMediator <|-- ConcreteColleague

    ConcreteMediator : HashMap Colleagues
    • Mediator:中介者的抽象对象,定义了同事对象到中介者对象的接口
    • Colleague:抽象同事类,抽象子系统的父类
    • ConcreteMediator:具体的中介者,实现抽象方法,他需要知到所有的具体的同事类,以集合形式管理并接受同事对象的消息完成抽象任务
    • ConcreteColleague:具体的同事类,每个同事只知道自己的行为,不了解其他同事类的行为,但他们都依赖中介者对象
    • 多个类相互耦合,会形成网状结构,使用中介者模式会使网状结构变为星型结构
    • 减少类间依赖,降低了耦合,符合迪米特法则
    • 中介者承担了较多的责任
1
2
3
4
5
6
7
8
9
10
11
package Mediator;

public abstract class Mediator {

public abstract void registerColleague(Colleague colleague);
public abstract void removeColleague(Colleague colleague);
// public abstract void adjust();
public abstract void getMessage(Colleague colleague,int index);

}

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

import java.util.ArrayList;
import java.util.List;

public class ConcreteMediator extends Mediator{

List<Colleague> list;

public ConcreteMediator() {
// TODO Auto-generated constructor stub
list = new ArrayList();
}

@Override
public void registerColleague(Colleague colleague) {
// TODO Auto-generated method stub
list.add(colleague);
}

@Override
public void removeColleague(Colleague colleague) {
// TODO Auto-generated method stub
list.remove(colleague);

}

@Override
public void getMessage(Colleague colleague,int index) {
// TODO Auto-generated method stub


// getMessage from colleague and do property action

}
}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Mediator;

public abstract class Colleague {

public Colleague(String name,Mediator mediator) {
// TODO Auto-generated constructor stub
this.name = name;
this.mediator = mediator;
}
String name;
Mediator mediator;
public abstract void sendMessage();

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Mediator;

public class ConcreteColleague extends Colleague{

public ConcreteColleague(String name,Mediator mediator) {
// TODO Auto-generated constructor stub
super(name,mediator);
}

@Override
public void sendMessage() {
// TODO Auto-generated method stub
this.mediator.getMessage(this,1);
}

}

备忘录模式

    • 在不破坏封装性的前提下捕获对象的状态,并在对象之外保存该状态,这样以后就可以将该对象回复到原先保存的状态
    • 备忘录模式属于行为模式
    • 即对对象的信心进行保存
    • 可以联合原型模式一起使用通过clone
    • 也可以通过序列化和反序列化实现

解释器模式

    • 在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元通过语法分析器形成语法分析树,最后形成一棵抽象的语法分析树,这里的词法分析器和语法分析器都可以看作为解释器
    • 解释器模式:指定一个表达式,定义它的文法的一种表示,并定义一个解释器,使用该解释器来解析语言中的句子
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    classDiagram
    class Context
    class Client
    class AbstratctExpression
    class TerminalExpression
    class NonTerminalExpression


    Context <|-- Client
    AbstratctExpression <|-- Client
    TerminalExpression <|-- AbstratctExpression
    NonTerminalExpression <|-- AbstratctExpression
    AbstratctExpression : Expression interpreter

  • Context:环境角色,含有解释器之外的全局信息

  • AbstractExpression:抽象表达式,声明一个抽象的解释操作,这个为抽象语法树中的所有结点共享

  • TerminalExpression:为终结符表达式,实现与文法中的终结相关的解释操作

  • NoneTerminalExpression:为非终结符表达式

状态模式

    • 主要用来解决对象在多种状态转换时,需要对外输出不同行为的问题。状态和行为是一一对应的,状态之间可以相互转化
    • 当一个对象内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类

策略模式

    • 策略模式定义算法族,分别封装起来,让他们相互替换,此模式让算法的变化独立于使用算法的用户
    • 算法体现了几个设计原则:
      1. 把变化的代码从不变的代码中分离出来
      2. 针对接口编程而不是具体的类(定义了策略接口)
      3. 更多的使用了组合和聚合而不是继承(里氏替换原则)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package Strategy;

public abstract class Duck {
Fly fly;
Quack quack;
void duckFly() {
this.fly.fly();
}
void duckQuack() {
this.quack.quack();
}



}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Strategy;

public class ToyDuck extends Duck{

public ToyDuck() {
// TODO Auto-generated constructor stub
this.fly = new BadFly();
this.quack = new BadQuack();

}



}

1
2
3
4
5
6
7
package Strategy;

public interface Fly {
void fly();

}

1
2
3
4
5
6
7
8
9
10
11
12
13
package Strategy;

public class BadFly implements Fly{

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

}

}

1
2
3
4
5
6
7
package Strategy;

public interface Quack {
void quack();

}

1
2
3
4
5
6
7
8
9
10
11
12
13
package Strategy;

public class BadQuack implements Quack{

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

}

}

职责链模式

    • 职责链模式,为请求创建一个接收者对象的链,这种模式对请求的发送者和接收者进行解耦
    • 职责链模式通常每个接收者都包含对另一个接收者的引用,若该接收者无法处理,则转交给引用的接收者
    • 避免了if...else...的使用,降低了程序的耦合度,体现了面向对象的思想
    • 使多个对象都有机会处理请求,从而避免了请求的发送者和接收者的紧密的耦合
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    classDiagram
    class Handler
    class ConcreteHandlerA
    class ConcreteHandlerAA

    class Request

    Handler : void getRequest
    Handler : Handler handler
    Handler <|-- Request

    Handler <|-- ConcreteHandlerA
    ConcreteHandlerA <|-- ConcreteHandlerAA
    ConcreteHandlerA : ConcreteHandlerAA aa
    • Handler:抽象的处理者,进行请求的接收,同时含有handler的聚合
    • ConcreteHandler:具体的处理者,进行具体请求的处理,可以访问他的后继处理者,若可以处理则处理后返回否则交由后继进行处理,形成职责链
    • Request:含有多个属性表示一个请求

补充

增强耦合的方法

  • 继承
  • if...else...(当出现多个if...else...时)

volatile关键词

摘自:https://www.cnblogs.com/zhengbin/p/5654805.html

先补充一下概念:Java 内存模型中的可见性、原子性和有序性。

可见性:

  可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉。通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制。

  可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果。另一个线程马上就能看到。比如:用volatile修饰的变量,就会具有可见性。volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线程是可见的。但是这里需要注意一个问题,volatile只能让被他修饰内容具有可见性,但不能保证它具有原子性。比如 volatile int a = 0;之后有一个操作 a++;这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就是这个操作同样存在线程安全问题。

  在 Java 中 volatile、synchronized 和 final 实现可见性。

原子性:

  原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作。再比如:a++; 这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性。java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。

  在 Java 中 synchronized 和在 lock、unlock 中操作保证原子性。

有序性:

  Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性,volatile 是因为其本身包含“禁止指令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。

 Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

  在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。

当对非 volatile 变量进行读写的时候,每个线程先从内存拷贝变量到CPU缓存中。如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的 CPU cache 中。

  而声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步。

当一个变量定义为 volatile 之后,将具备两种特性:

  1.保证此变量对所有的线程的可见性,这里的“可见性”,如本文开头所述,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存(详见:Java内存模型)来完成。

  2.禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)。

volatile 性能:

  volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。

浅拷贝和深拷贝

浅拷贝
    • 若拷贝的值为基本数据类型,则拷贝会拷贝一份数据值
    • 若拷贝的值为对象类型,则浅拷贝只会拷贝一份引用,即指向的为相同的对象
深拷贝
    1. 通过重写clone函数进行深拷贝:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      public class DeepClone implements Cloneable,Serializable{
      public CopiedClass c = new CopiedClass();

      @Override
      protected Object clone() throws CloneNotSupportedException {
      // TODO Auto-generated method stub
      DeepClone instance = null;
      instance = (DeepClone) super.clone();
      instance.c = (CopiedClass) c.clone();

      return instance;
      }

      }

    2. 通过序列化实现深拷贝(推荐)

      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
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      public class DeepClone implements Cloneable,Serializable{
      public CopiedClass c = new CopiedClass();

      public DeepClone deepClone() {
      DeepClone instance = null;
      ByteArrayOutputStream bos = null;
      ObjectOutputStream oos = null;
      ByteArrayInputStream bis = null;
      ObjectInputStream ois = null;

      try {
      // 序列化
      bos = new ByteArrayOutputStream();
      oos = new ObjectOutputStream(bos);
      oos.writeObject(this);

      // 反序列化
      bis = new ByteArrayInputStream(bos.toByteArray());
      ois = new ObjectInputStream(bis);
      instance = (DeepClone)ois.readObject();
      } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }finally {
      try {
      bos.close();
      oos.close();
      bis.close();
      ois.close();
      } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }

      }

      return instance;


      }


      }

      // 注意,待序列化中的所有引用属性都需要进行序列化

      public class CopiedClass implements Cloneable,Serializable{

      String name;
      public CopiedClass(String name) {
      // TODO Auto-generated constructor stub
      this.name = name;
      }

      public CopiedClass() {
      // TODO Auto-generated constructor stub
      }

      @Override
      protected Object clone() throws CloneNotSupportedException {
      // TODO Auto-generated method stub
      return super.clone();
      }

      @Test
      public void test() throws CloneNotSupportedException {
      CopiedClass a = new CopiedClass("ych");
      CopiedClass b = (CopiedClass) a.clone();
      }


      }


Iteraior接口

    • boolean hasNext()
    • E next()
    • void remove()
  • import java.util.ArrayList; import java.util.Iterator; import java.util.List;

    public class A { List list = new ArrayList();

    public A() { // TODO Auto-generated constructor stub list.add(new B("66")); list.add(new B("77")); list.add(new B("88"));

    }

    public Iterator iterator() { return new AIterator(); } // 内部类 class AIterator implements Iterator{

      int index = 0;
    
      public AIterator() {
          // TODO Auto-generated constructor stub
      }
      @Override
      public boolean hasNext() {
          // TODO Auto-generated method stub
          if(index < list.size())return true;
          return false;
      }
      @Override
      public Object next() {
          // TODO Auto-generated method stub
          return list.get(index++);
      }

    }

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    ```java
    package Iterator.MyIterator;

    public class B {
    String name;
    public B(String name) {
    // TODO Auto-generated constructor stub
    this.name = name;
    }

    public String toString() {
    return name;
    }

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package Iterator.MyIterator;

    import java.util.Iterator;

    import org.junit.jupiter.api.Test;

    public class TestClass {
    @Test
    public void test() {
    A a = new A();
    Iterator iterator = a.iterator();
    while(iterator.hasNext()) {
    System.out.println(iterator.next());
    }
    }
    }

JDK Observable源码分析

Arrays.sort的lambda表达式用法

1
2
3
4
5
6
7
8
9
10
11
@Test
public void test() {
Integer arr[] = {9,6,3,8,5,2,7,4,1};
Arrays.sort(arr,(var1,var2) -> {
if(var1.compareTo(var2) > 0)return 1;
else return -1;
});

System.out.println(Arrays.toString(arr));

}