一、简介
1.背景
clipboard.png

2.什么是设计模式
clipboard.png
clipboard.png

3.为什么使用设计模式
clipboard.png

二、单例模式(Singleton)
1.概述

单例模式指的是一个类只能有一个实例,这样的类被称为单例类,或者单态类,即Singleton Class。

2.单例类的特点

1)单例类只可有一个实例
2)它必须自己创立这唯一的一个实例
3)它必须给所有其他的类提供自己这一实例

3.单例模式的实现
单例模式有两种常见的实现方式,被称为饿汉式和懒汉式。
饿汉式:加载类的时候就初始化一个实例。
懒汉式:加载类的时候不初始化,当第一次使用实例时才初始化。
clipboard.png

4.单例类的特点总结
1)构造方法是private权限,保证其他类无法创建该类实例,只能该类自身创建
2)声明一个static修饰的自身实例,保证该实例永远只是一个
3)提供一个public方法,返回定义的static自身实例
5.代码演示
5.1饿汉式

public class EagerSingleton {
  //饿汉式单例:声明并创建一个自身的static实例
  private static EagerSingleton instance = new EagerSingleton();

  //构造方法是private
  private EagerSingleton() {
  }

  //提供静态public方法,返回自己创建的唯一实例
  public static EagerSingleton getInstance() {
      return instance;
  }
}

5.2懒汉式

public class LazySingleton {
  //懒汉式单例:只声明,不创建
  private static LazySingleton instance = null;

  //构造方法为private
  private LazySingleton() {
  }

  //当第一次调用getInstance方法时,创建唯一实例
  public static LazySingleton getInstance() {
      if (instance == null) {
          instance = new LazySingleton();
      }
      return instance;
  }
}

6.API中的单例模式
API中的Runtime类是一个单例类
没有公共的构造方法
提供静态方法getRuntime()返回该类实例

public static void main(String[] args) {
    //获得多个实例,输出后如果地址相同,说明是同一个实例
    EagerSingleton eager1 = EagerSingleton.getInstance();
    EagerSingleton eager2 = EagerSingleton.getInstance();
    System.out.println(eager1);
    System.out.println(eager2);
    System.out.println("--------------------");
    LazySingleton lazy1 = LazySingleton.getInstance();
    LazySingleton lazy2 = LazySingleton.getInstance();
    System.out.println(lazy1);
    System.out.println(lazy2);
    System.out.println("--------------------");
    Runtime r1 = Runtime.getRuntime();
    Runtime r2 = Runtime.getRuntime();
    Runtime r3 = Runtime.getRuntime();
    System.out.println(r1);
    System.out.println(r2);
    System.out.println(r3);
    try {
        r1.exec("calc.exe");//打开计算机
    } catch (IOException e) {
        e.printStackTrace();
    }
}    

clipboard.png

三、适配器模式(Adapter)
1.概述

适配器模式把一个类的接口变换成客户端所期待的另一种接口。
适配器模式使原本无法在一起工作的两个类能够在一起工作。

2.生活中的例子
美国的生活用电压是110伏,而中国的电压是220伏,如果要在中国使用在美国购买的电器,就必须有一个能把220伏电压转换成110伏电压的变压器。
3.适配器模式分类

1)类形式的适配器——使用继承实现适配器模式(is a)
2)实例形式的适配器——使用关联实现适配器模式(has a)

4.类形式的适配器
4.1类形式
clipboard.png
目标(Target):就是我们所期待得到的接口。注意,由于这里讨论的是类变压器模式,因此目标不可以是类,而是接口。
源(Adaptee):现有需要适配的接口。
变压器(Adapter):变压器类是本模块的核心。变压器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是实类。
4.2.代码演示

/**
 * Target是目标类,也就是需要使用的类型
 */
public interface Target {

  /**
   * 该方法与源Adaptee中的方法相同
   */
  void SampleOperation1();
  /**
   * 该方法是目标类中的新方法
   */
  void SampleOperation2();
}

-----------------------------------------------------------------

/**
 * 源类,也就是需要被适配的类
 */
public class Adaptee {
  /**
   * 模拟源类中的方法
   */
  public void SampleOperation1() {
      System.out.println("调用Adaptee类中的SampleOperation1方法");
  }
}

-----------------------------------------------------------------

/**
 * 适配器类Adapter,作用是把Adaptee变成Target
 * 实现方法为:Adapter继承Adaptee,实现Target
 */
public class Adapter extends Adaptee implements Target {
  /**
   * 实现接口Target中的SampleOperation2方法
   * SampleOperation1方法直接使用Adaptee中的方法
   */
  @Override
  public void SampleOperation2() {
      System.out.println("调用Adapter类中的SampleOperation2方法");
  }
}    

----------------------------------------------------------------

//测试类
public class Client {
  public static void request(Target t) {
      t.SampleOperation1();
      t.SampleOperation2();
  }

  public static void main(String[] args) {
      request(new Adapter());
      //调用Adaptee类中的SampleOperation1方法
      //调用Adapter类中的SampleOperation2方法
  }
}

5.实例形式的适配器
5.1实例形式
clipboard.png

5.2代码演示
Target.java和Adaptee.java 代码没变化

/**
 * 适配器类
 */
public class Adapter implements Target {
  private Adaptee adaptee;

  public Adapter(Adaptee adaptee) {
      super();
      this.adaptee = adaptee;
  }

  //直接调用Adaptee类中的SampleOperation1方法
  public void SampleOperation1() {
      adaptee.SampleOperation1();
  }

  public void SampleOperation2() {
      System.out.println("调用Adapter类中的SampleOpertion2方法");
  }
}

四、装饰器模式(Decorator)
1.概述

装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。
装饰模式使用原来被装饰的类的一个子类的实例,把客户端的调用委派到被装饰类。

2.装饰模式结构
clipboard.png

抽象构件(Component):给出一个抽象接口,以规范准备接受附加责任的对象。
具体构件(ConcreteComponent):定义一个将要接收附加责任的类。
装饰(Decorator):持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(ConcreteDecorator):负责给构件对象“贴上”附件的责任。

3.应用场景:
1)需要扩展一个类的功能,或给一个类增加附加责任。
2)需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
3)需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
4.代码演示

/**
 * 组件类,是准备随时扩展新功能的类型
 */
public interface Component {
  void SampleOperation();
}


/**
 * 具体组件类,功能将被动态扩展
 */
public class ConcreteComponent implements Component {
  public void SampleOperation() {
      System.out.println("调用ConcreteComponent具体组件类中的SampleOperation方法");
  }
}


/**
 * 装饰器类,实现了Component接口,同时关联了Component
 */
public class Decorator implements Component {
  private Component component;
  public Decorator(Component com) {
      this.component = com;
  }

  public void SampleOperation() {
      System.out.println("Decorator装饰器类对SampleOperation方法进行了扩展");
      component.SampleOperation();
  }
}


/**
 * 具体装饰器类,继承了Decorator装饰器类
 */
public class ConcreteDecorator extends Decorator {
  public ConcreteDecorator(Component component) {
      super(component);
  }

  public void SampleOperation() {
      super.SampleOperation();
      System.out.println("ConcreteDecorator具体装饰器类对SampleOperation方法进行了扩展");
  }
}


/**
 * 客户端,用不同的组件对象去调用方法
 */
public class Client{
  public static void main(String[] args) {
      //创建组件对象component,调用SampleOperation方法
      Component component = new ConcreteComponent();
      component.SampleOperation();
      System.out.println("-----------------分割线----------------");

      //使用Decorator装饰组件对象component,调用SampleOperation方法
      Component decorator = new Decorator(component);
      decorator.SampleOperation();
      System.out.println("-----------------分割线----------------");

      //使用ConcreteDecorator装饰组件component,调用SampleOperation方法
      Component concreteComponent = new ConcreteDecorator(component);
      concreteComponent.SampleOperation();
      System.out.println("-----------------分割线----------------");
  }
}

执行结果:
clipboard.png

5.java的I/O中的装饰模式
clipboard.png

clipboard.png

五.代理模式(Proxy)
1.概述

所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。
在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用,进行额外的预处理和后续处理。

2.代理模式的类图
clipboard.png

抽象主题角色(Subject):声明了真实主题和代理主题的共同接口,这样在任何可用真实主题的地方都可以使用代理主题。
代理主题角色(Proxy):代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象,代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作。
真实主题角色(RealSubject):定义了代理角色所代表的真实对象。
3.代码演示

/**
 * 抽象主题角色,定义了真实主题和代理主题都要实现的方法
 */
public abstract class Subject {
  public abstract void request();
}

/**
 * 真实主题
 */
public class RealSubject extends Subject {
    public RealSubject() {
    }

  public void request() {
      System.out.println("调用真实主题的request方法");
  }
}
/**
 * 代理主题
 */
public class ProxySubject extends Subject {
   //关联真实主题
  private RealSubject realSubject;
  public void ProxySubject() {
  }

//覆盖抽象主题的方法,在对真实主题调用request方法的前后,加上了预处理和后处理
  public void request() {
      preRequest();
     if (realSubject == null) {
          realSubject = new RealSubject();
          realSubject.request();
      }
      postRequest();
  }

  private void preRequest() {
      System.out.println("调用代理主题的preRequest方法");
  }

  private void postRequest() {
      System.out.println("调用代理主题的postRequest方法");
  }
}

/**
 * 客户端
 */
public class Client {
  static public void test(Subject subject) {
      subject.request();
  }

  public static void main(String[] args) {
      //调用真实主题的request方法
      test(new RealSubject());

      System.out.println("----------------分割线---------------");

      //调用代理主题的request方法
      test(new ProxySubject());
  }
}

打印结果:
clipboard.png


fangyanr
6 声望1 粉丝