几种常见的设计模式

Java 中一般认为有23种设计模式,当然暂时不需要所有的都会,但是其中常见的几种设计模式应该去掌握。
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

  1. 单例模式

所谓的单例设计指的是一个类只允许产生一个实例化对象。
最好理解的一种设计模式,分为懒汉式和饿汉式。

饿汉式:构造方法私有化,外部无法产生新的实例化对象,只能通过static方法取得实例化对象

class Singleton {
/**
* 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
/
private static Singleton instance = new Singleton();
/
*
* private 声明构造
*/
private Singleton() {

}
/**
 * 返回对象实例
 */
public static Singleton getInstance() {
    return instance;
}

public void print() {
    System.out.println("Hello Singleton...");
}

}

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

懒汉式:当第一次去使用Singleton对象的时候才会为其产生实例化对象的操作

class Singleton {

/**
 * 声明变量
 */
private static volatile Singleton singleton = null;

/**
 * 私有构造方法
 */
private Singleton() {

}

/**
 * 提供对外方法
 * @return 
 */
public static Singleton getInstance() {
    // 还未实例化
    if (singleton == null) {
        synchronized (Singleton.class) {
            if (singleton == null) {
                singleton = new Singleton();
            }
        }
    }
    return singleton;
}
public void print() {
    System.out.println("Hello World");
}

}

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

当多个线程并发执行 getInstance 方法时,懒汉式会存在线程安全问题,所以用到了 synchronized 来实现线程的同步,当一个线程获得锁的时候其他线程就只能在外等待其执行完毕。而饿汉式则不存在线程安全的问题。
2. 工厂设计模式

工厂模式分为工厂方法模式和抽象工厂模式。
工厂方法模式

工厂方法模式:
1. 工厂方法模式分为三种:普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
2. 多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。
3. 静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。
  1. 普通工厂模式

建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

interface Sender {
void Send();
}

class MailSender implements Sender {

@Override
public void Send() {
    System.out.println("This is mail sender...");
}

}

class SmsSender implements Sender {

@Override
public void Send() {
    System.out.println("This is sms sender...");
}

}

public class FactoryPattern {
public static void main(String[] args) {
Sender sender = produce(“mail”);
sender.Send();
}
public static Sender produce(String str) {
if (“mail”.equals(str)) {
return new MailSender();
} else if (“sms”.equals(str)) {
return new SmsSender();
} else {
System.out.println(“输入错误…”);
return null;
}
}
}

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
  1. 多个工厂方法模式

该模式是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

interface Sender {
void Send();
}

class MailSender implements Sender {

@Override
public void Send() {
    System.out.println("This is mail sender...");
}

}

class SmsSender implements Sender {

@Override
public void Send() {
    System.out.println("This is sms sender...");
}

}

class SendFactory {
public Sender produceMail() {
return new MailSender();
}

public Sender produceSms() {
    return new SmsSender();
}

}

public class FactoryPattern {
public static void main(String[] args) {
SendFactory factory = new SendFactory();
Sender sender = factory.produceMail();
sender.Send();
}
}

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
  1. 静态工厂方法模式

将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

interface Sender {
void Send();
}

class MailSender implements Sender {

@Override
public void Send() {
    System.out.println("This is mail sender...");
}

}

class SmsSender implements Sender {

@Override
public void Send() {
    System.out.println("This is sms sender...");
}

}

class SendFactory {
public static Sender produceMail() {
return new MailSender();
}

public static Sender produceSms() {
    return new SmsSender();
}

}

public class FactoryPattern {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.Send();
}
}

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

抽象工厂模式

工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要扩展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?
那么这就用到了抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

interface Provider {
Sender produce();
}

interface Sender {
void Send();
}

class MailSender implements Sender {

public void Send() {
    System.out.println("This is mail sender...");
}

}

class SmsSender implements Sender {

public void Send() {
    System.out.println("This is sms sender...");
}

}

class SendMailFactory implements Provider {

public Sender produce() {
    return new MailSender();
}

}

class SendSmsFactory implements Provider {

public Sender produce() {
    return new SmsSender();
}

}

public class FactoryPattern {
public static void main(String[] args) {
Provider provider = new SendMailFactory();
Sender sender = provider.produce();
sender.Send();
}
}

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
  1. 建造者模式

工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性。

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

/**

  • @Author: LiuWang
  • @Created: 2018/8/6 17:47
    */

abstract class Builder {
/**
* 第一步:装CPU
*/
public abstract void buildCPU();

/**
 * 第二步:装主板
 */
public abstract void buildMainBoard();

/**
 * 第三步:装硬盘
 */
public abstract void buildHD();

/**
 * 获得组装好的电脑
 * @return
 */
public abstract Computer getComputer();

}

/**

  • 装机人员装机
    */
    class Director {
    public void Construct(Builder builder) {
    builder.buildCPU();
    builder.buildMainBoard();
    builder.buildHD();
    }
    }

/**

  • 具体的装机人员
    */
    class ConcreteBuilder extends Builder {

    Computer computer = new Computer();

    @Override
    public void buildCPU() {
    computer.Add(“装CPU”);
    }

    @Override
    public void buildMainBoard() {
    computer.Add(“装主板”);
    }

    @Override
    public void buildHD() {
    computer.Add(“装硬盘”);
    }

    @Override
    public Computer getComputer() {
    return computer;
    }
    }

class Computer {

/**
 * 电脑组件集合
 */
private List<String> parts = new ArrayList<String>();

public void Add(String part) {
    parts.add(part);
}

public void print() {
    for (int i = 0; i < parts.size(); i++) {
        System.out.println("组件:" + parts.get(i) + "装好了...");
    }
    System.out.println("电脑组装完毕...");
}

}

public class BuilderPattern {

public static void main(String[] args) {
    Director director = new Director();
    Builder builder = new ConcreteBuilder();
    director.Construct(builder);
    Computer computer = builder.getComputer();
    computer.print();
}

}

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  1. 适配器设计模式

适配器模式是将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的的类的兼容性问题。主要分三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

  1. 类的适配器模式:

class Source {
public void method1() {
System.out.println(“This is original method…”);
}
}

interface Targetable {

/**
 * 与原类中的方法相同
 */
public void method1();

/**
 * 新类的方法
 */
public void method2();

}

class Adapter extends Source implements Targetable {

@Override
public void method2() {
    System.out.println("This is the targetable method...");
}

}

public class AdapterPattern {
public static void main(String[] args) {
Targetable targetable = new Adapter();
targetable.method1();
targetable.method2();
}
}

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
  1. 对象的适配器模式

基本思路和类的适配器模式相同,只是将Adapter 类作修改,这次不继承Source 类,而是持有Source 类的实例,以达到解决兼容性的问题。

class Source {
public void method1() {
System.out.println(“This is original method…”);
}
}

interface Targetable {

/**
 * 与原类中的方法相同
 */
public void method1();

/**
 * 新类的方法
 */
public void method2();

}

class Wrapper implements Targetable {

private Source source;

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

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

@Override
public void method2() {
    System.out.println("This is the targetable method...");
}

}

public class AdapterPattern {
public static void main(String[] args) {
Source source = new Source();
Targetable targetable = new Wrapper(source);
targetable.method1();
targetable.method2();
}
}

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
  1. 接口的适配器模式

接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。

/**

  • 定义端口接口,提供通信服务
    /
    interface Port {
    /
    *

    • 远程SSH端口为22
      */
      void SSH();

    /**

    • 网络端口为80
      */
      void NET();

    /**

    • Tomcat容器端口为8080
      */
      void Tomcat();

    /**

    • MySQL数据库端口为3306
      */
      void MySQL();
      }

/**

  • 定义抽象类实现端口接口,但是什么事情都不做
    */
    abstract class Wrapper implements Port {
    @Override
    public void SSH() {

    }

    @Override
    public void NET() {

    }

    @Override
    public void Tomcat() {

    }

    @Override
    public void MySQL() {

    }
    }

/**

  • 提供聊天服务
  • 需要网络功能
    */
    class Chat extends Wrapper {
    @Override
    public void NET() {
    System.out.println(“Hello World…”);
    }
    }

/**

  • 网站服务器

  • 需要Tomcat容器,Mysql数据库,网络服务,远程服务
    */
    class Server extends Wrapper {
    @Override
    public void SSH() {
    System.out.println(“Connect success…”);
    }

    @Override
    public void NET() {
    System.out.println(“WWW…”);
    }

    @Override
    public void Tomcat() {
    System.out.println(“Tomcat is running…”);
    }

    @Override
    public void MySQL() {
    System.out.println(“MySQL is running…”);
    }
    }

public class AdapterPattern {

private static Port chatPort = new Chat();
private static Port serverPort = new Server();

public static void main(String[] args) {
    // 聊天服务
    chatPort.NET();

    // 服务器
    serverPort.SSH();
    serverPort.NET();
    serverPort.Tomcat();
    serverPort.MySQL();
}

}

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  1. 装饰模式

顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。

interface Shape {
void draw();
}

/**

  • 实现接口的实体类
    */
    class Rectangle implements Shape {

    @Override
    public void draw() {
    System.out.println(“Shape: Rectangle…”);
    }
    }

class Circle implements Shape {

@Override
public void draw() {
    System.out.println("Shape: Circle...");
}

}

/**

  • 创建实现了 Shape 接口的抽象装饰类。
    */
    abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

    public ShapeDecorator(Shape decoratedShape) {
    this.decoratedShape = decoratedShape;
    }

    @Override
    public void draw() {
    decoratedShape.draw();
    }
    }

/**

  • 创建扩展自 ShapeDecorator 类的实体装饰类。
    */
    class RedShapeDecorator extends ShapeDecorator {

    public RedShapeDecorator(Shape decoratedShape) {
    super(decoratedShape);
    }

    @Override
    public void draw() {
    decoratedShape.draw();
    setRedBorder(decoratedShape);
    }

    private void setRedBorder(Shape decoratedShape) {
    System.out.println(“Border Color: Red”);
    }
    }

/**

  • 使用 RedShapeDecorator 来装饰 Shape 对象。
    */
    public class DecoratorPattern {
    public static void main(String[] args) {
    Shape circle = new Circle();
    Shape redCircle = new RedShapeDecorator(new Circle());
    Shape redRectangle = new RedShapeDecorator(new Rectangle());
    System.out.println(“Circle with normal border”);
    circle.draw();

     System.out.println("\nCircle of red border");
     redCircle.draw();
    
     System.out.println("\nRectangle of red border");
     redRectangle.draw();
    

    }
    }

    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

  1. 策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数。策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

/**

  • 抽象算法的策略类,定义所有支持的算法的公共接口
    /
    abstract class Strategy {
    /
    *
    • 算法方法
      */
      public abstract void AlgorithmInterface();
      }

/**

  • 具体算法A
    */
    class ConcreteStrategyA extends Strategy {
    //算法A实现方法
    @Override
    public void AlgorithmInterface() {
    System.out.println(“算法A的实现”);
    }
    }

/**

  • 具体算法B
    /
    class ConcreteStrategyB extends Strategy {
    /
    *
    • 算法B实现方法
      */
      @Override
      public void AlgorithmInterface() {
      System.out.println(“算法B的实现”);
      }
      }

/**

  • 具体算法C
    */
    class ConcreteStrategyC extends Strategy {
    @Override
    public void AlgorithmInterface() {
    System.out.println(“算法C的实现”);
    }
    }

/**

  • 上下文,维护一个对策略类对象的引用
    */
    class Context {
    Strategy strategy;

    public Context(Strategy strategy) {
    this.strategy = strategy;
    }

    public void contextInterface(){
    strategy.AlgorithmInterface();
    }
    }

/**

  • 客户端代码:实现不同的策略
    */
    public class StrategyPattern {
    public static void main(String[] args) {

     Context context;
    
     context = new Context(new ConcreteStrategyA());
     context.contextInterface();
    
     context = new Context(new ConcreteStrategyB());
     context.contextInterface();
    
     context = new Context(new ConcreteStrategyC());
     context.contextInterface();
    

    }
    }

    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

  1. 代理模式

代理模式指给一个对象提供一个代理对象,并由代理对象控制对原对象的引用。代理可以分为静态代理和动态代理。
通过代理模式,可以利用代理对象为被代理对象添加额外的功能,以此来拓展被代理对象的功能。可以用于计算某个方法执行时间,在某个方法执行前后记录日志等操作。

  1. 静态代理

静态代理需要我们写出代理类和被代理类,而且一个代理类和一个被代理类一一对应。代理类和被代理类需要实现同一个接口,通过聚合使得代理对象中有被代理对象的引用,以此实现代理对象控制被代理对象的目的。

/**

  • 代理类和被代理类共同实现的接口
    */
    interface IService {

    void service();
    }

/**

  • 被代理类
    */
    class Service implements IService{

    @Override
    public void service() {
    System.out.println(“被代理对象执行相关操作”);
    }
    }

/**

  • 代理类
    /
    class ProxyService implements IService{
    /
    *

    • 持有被代理对象的引用
      */
      private IService service;

    /**

    • 默认代理Service类
      */
      public ProxyService() {
      this.service = new Service();
      }

    /**

    • 也可以代理实现相同接口的其他类
    • @param service
      */
      public ProxyService(IService service) {
      this.service = service;
      }

    @Override
    public void service() {
    System.out.println(“开始执行service()方法”);
    service.service();
    System.out.println(“service()方法执行完毕”);
    }
    }

//测试类
public class ProxyPattern {

public static void main(String[] args) {
    IService service = new Service();
    //传入被代理类的对象
    ProxyService proxyService = new ProxyService(service);
    proxyService.service();
}

}

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
  1. 动态代理

JDK 1.3 之后,Java通过java.lang.reflect包中的三个类Proxy、InvocationHandler、Method来支持动态代理。动态代理常用于有若干个被代理的对象,且为每个被代理对象添加的功能是相同的(例如在每个方法运行前后记录日志)。

动态代理的代理类不需要我们编写,由Java自动产生代理类源代码并进行编译最后生成代理对象。
创建动态代理对象的步骤:

  1. 指明一系列的接口来创建一个代理对象
  2. 创建一个调用处理器(InvocationHandler)对象
  3. 将这个代理指定为某个其他对象的代理对象
  4. 在调用处理器的invoke()方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要的操作

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

/**

  • 代理类和被代理类共同实现的接口
    */
    interface IService {
    void service();
    }

class Service implements IService{

@Override
public void service() {
    System.out.println("被代理对象执行相关操作");
}

}

class ServiceInvocationHandler implements InvocationHandler {

/**
 * 被代理的对象
 */
private Object srcObject;

public ServiceInvocationHandler(Object srcObject) {
    this.srcObject = srcObject;
}

@Override
public Object invoke(Object proxyObj, Method method, Object[] args) throws Throwable {
    System.out.println("开始执行"+method.getName()+"方法");
    //执行原对象的相关操作,容易忘记
    Object returnObj = method.invoke(srcObject,args);
    System.out.println(method.getName()+"方法执行完毕");
    return returnObj;
}

}

public class ProxyPattern {
public static void main(String[] args) {
IService service = new Service();
Class<? extends IService> clazz = service.getClass();

    IService proxyService = (IService) Proxy.newProxyInstance(clazz.getClassLoader(),
                                    clazz.getInterfaces(), new ServiceInvocationHandler(service));
    proxyService.service();
}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值