Java的23种设计模式

创建型模式:静态工厂模式

简要描述:用白话文来讲,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

/** 发送信息的总接口 */
public interface Sender {
  public void send();
}
/** 邮件发送信息的实现类 */
public class MailSender implements Sender {
  @Override
  public void send() {
    System.out.println("This is MailSender!");
  }
}
/** 短信发送信息的实现类 */
public class SmsSender implements Sender {
  @Override
  public void send() {
    System.out.println("This is SmsSender!");
  }
}
/** 工厂类 */
public class SenderFactory {
  public static Sender getMailSenderInstance() {
    return new MailSender();
  }
  public static Sender getSmsSenderInstance() {
    return new SmsSender();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    SenderFactory.getMailSenderInstance().send();
    SenderFactory.getSmsSenderInstance().send();
  }
}

创建型模式:抽象工厂模式

简要描述:静态工厂模式有一个问题,就是实例的创建依赖于工厂方法,也就是说,如果想要扩展程序,必须要对工厂类进行修改,这违背了闭包原则,这个时候就要用到抽象工厂模式了。核心原理就是给每一个实现类都创建一个一一对应的工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就行了,不需要改之前的代码的。

/** 发送信息的总接口 */
public interface Sender {
  public void send();
}
/** 邮件发送信息的实现类 */
public class MailSender implements Sender {
  @Override
  public void send() {
    System.out.println("This is MailSender!");
  }
}
/** 短信发送信息的实现类 */
public class SmsSender implements Sender {
  @Override
  public void send() {
    System.out.println("This is SmsSender!");
  }
}
/** 抽象工厂接口 */
public interface Provider {
  public Sender produce();
}
/** 邮件发送信息的工厂类 */
public class MailSenderFactory implements Provider {
  @Override
  public Sender produce() {
    return new MailSender();
  }
}
/** 短信发送信息的工厂类 */
public class SmsSenderFactory implements Provider {
  @Override
  public Sender produce() {
    return new SmsSender();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Provider mailPro = new MailSenderFactory();
    mailPro.produce().send();
    Provider smsPro = new SmsSenderFactory();
    smsPro.produce().send();
  }
}

假如现在有新需求,需要新增加一个电话发送信息的功能,则只需要增加电话发送功能和增加电话工厂类即可,不需要对之前的代码做任何改动,这就满足了“对扩展开放,对修改关闭”的设计原则。

/** 电话发送信息的实现类 */
public class PhoneSender implements Sender {
  @Override
  public void send() {
    System.out.println("This is PhoneSender!");
  }
}
/** 电话发送信息的工厂类 */
public class PhoneSenderFactory implements Provider {
  @Override
  public Sender produce() {
    return new PhoneSender();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Provider phonePro = new PhoneSenderFactory();
    phonePro.produce().send();
  }
}

创建型模式:单例模式

简要描述:在Java应用中,单例模式能保证在一个JVM中该对象只有一个实例存在。
个人觉得有以下几个好处:
1、某些类创建得比较频繁,又特别是一些大型的对象,这对系统将是一笔大的开销;
2、省去了new操作符,降低了系统内存的使用频率,减轻了垃圾回收机制GC的压力;
3、有些类在某种场景中,要求只能有一个实例,单例模式可以实现。

现假设Singleton这个类要求只能存在一个实例。此处我使用的是内部类来实现单例,因为JVM内部机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的:

public class Singleton {
  /** 私有构造方法,防止单例对象被实例化 */
  private Singleton() {
    System.out.println("单例对象的私有构造方法。");
  }
  /** 使用内部类来维护单例对象,保证对象只被创建一次 */
  private static class SingletonFactory {
    private static Singleton singleton = new Singleton();
  }
  /** 获取实例 */
  public static final Singleton getInstance() {
    return SingletonFactory.singleton;
  }
  /** 如果对象被用于序列化,可以保证对象在序列化前后保持一致 */
  public Object readResolve() {
    return getInstance();
  }
}
/**
  测试类(此处我测试的时候是启动了10000个线程同时去获取实例,可能有的机器上会内存溢出,可以适当改一下循环
  次数,1000可以,100也可以,最主要是想说明在多线程环境中,该单例同样能保证只创建一个实例)
 */
public class TestClass {
  public static void main(String[] args) {
    for (int i = 1; i <= 10000; i++) {
      System.out.println("执行第" + i + "次。");
      new MyThread().start();
    }
  }
  private static class MyThread extends Thread {
    @Override
    public void run() {
      Singleton.getInstance();
    }
  }
}

创建型模式:建造者模式

简要描述:建造者模式是将很多功能集成到一个类里,这个类可以创造出比较复杂的东西。
它与工厂模式的区别就是:工厂模式关注的是单个产品的创建,而建造者模式则关注的是复合对象的创建。
具体要创建一个什么样的复合对象,得依据实际情况而定,这里我就举一个简单的例子:

/** 发送信息的总接口 */
public interface Sender {
  public void send();
}
/** 邮件发送信息的实现类 */
public class MailSender implements Sender {
  @Override
  public void send() {
    System.out.println("This is MailSender!");
  }
}
/** 短信发送信息的实现类 */
public class SmsSender implements Sender {
  @Override
  public void send() {
    System.out.println("This is SmsSender!");
  }
}
/** 建造者工厂类 */
public class BuilderFactory {
  private List<Sender> list = new ArrayList<Sender>();
  public List<Sender> produceMailSender(Integer count) {
    for (int i = 0; i < count; i++) {
      list.add(new MailSender());
    }
    return list;
  }
  public List<Sender> produceSmsSender(Integer count) {
    for (int i = 0; i < count; i++) {
      list.add(new SmsSender());
    }
    return list;
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    BuilderFactory builder = new BuilderFactory();
    List<Sender> mailList = builder.produceMailSender(10);
    System.out.println("mailList.size() = " + mailList.size());
    mailList.get(0).send();
    List<Sender> smsList = builder.produceSmsSender(20);
    System.out.println("smsList.size() = " + smsList.size());
    smsList.get(10).send();
  }
}

创建型模式:原型模式

简要描述:原型模式就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。(对象的复制分为浅复制和深复制,深复制必须要使用二进制流去实现)

/** 假设要给Student这个实体类实现复制 */
public class Student implements Cloneable, Serializable {
  public static final long serialVersionUID = 1L;
  private String name;
  private Integer age;
  private String address;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name
  }
  public Integer getAge() {
    return age;
  }
  public void setAge(Integer age) {
    this.age = age;
  }
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }
  /** 浅复制 */
  public Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
  /** 深复制 */
  public Object deepClone() throws IOException, ClassNotFoundException {
    //写出当前对象到二进制流
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(this);
    //读入二进制流产生新的对象并返回
    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bais);
    return ois.readObject();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    //构造对象
    Student stu = new Student();
    stu.setName("Jason Rao");
    stu.setAge(32);
    stu.setAddress("China");
    try {
      //深复制测试
      Student stuDeepClone = (Student) stu.deepClone();
      System.out.println(stuDeepClone.getName());
      //对深复制后的新对象进行值变更操作
      stuDeepClone.setName("Hutcher");
      //新对象值发生变化,原对象的值未发生变化,说明是深复制
      System.out.println(stuDeepClone.getName());
      System.out.println(stu.getName());
      
      //浅复制测试
      Student stuClone = (Student) stu.clone();
      System.out.println(stuClone.getName());
      //对浅复制后的新对象进行值变更操作
      stuClone.setName("Juntcher");
      //新对象值发生变化,原对象的值也发生变化,说明是浅复制
      System.out.println(stuClone.getName());
      System.out.println(stu.getName());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

结构型模式:适配器模式

类的适配器

简要描述:类的适配器模式的核心思想就是将某个源类中待适配的方法扩展到另一个接口中去

/** 源类中的method1方法待适配 */
public class Source {
  public void method1() {
    System.out.println("This is Source's method1!");
  }
}
/** 这是扩展后的接口 */
public interface Targetable {
  public void method1();
  public void method2();
}
/** 适配器类 */
public class Adapter extends Source implements Targetable {
  @Override
  public void method2() {
    System.out.println("This is Targetable's method2!");
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Targetable target = new Adapter();
    target.method1();
    target.method2();
  }
}

对象的适配器

简要描述:对象的适配器模式跟类的适配器模式的基本思路都一样,区别就是对象的适配器不用继承源类,而是持有源类的对象,这样可以解决与源类的兼容性问题。

/** 源类中有method1方法待适配 */
public class Source {
  public void method1() {
    System.out.println("This is Source's method1!");
  }
}
/** 扩展之后的接口 */
public interface Targetable {
  public void method1();
  public void method2();
}
/** 适配器类 */
public class Adapter implements Targetable {
  private Source source;
  public Adapter(Source source) {
    this.source = source;
  }
  @Override
  public void method1() {
    source.method1();
  }
  @Override
  public void method2() {
    System.out.println("This is Targetable's method2!");
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Source source = new Source();
    Targetable target = new Adapter(source);
    target.method1();
    target.method2();
  }
}

接口的适配器

简要描述:当某个接口中有很多很多抽象方法,且我们只需要实现其中某几个方法的时候,如果我们用实现类直接去implements这个接口的话,就必须要实现这个接口中的所有方法,这样明显很浪费,此时,我们就可以借助于一个抽象类来实现接口的适配,这就是接口的适配器模式。

/** 待适配的接口 */
public interface Sourceable {
  public void method1();
  public void method2();
}
/** 适配器抽象类 */
public abstract class Wrapper implements Sourceable {
  @Override
  public void method1() {
  }
  @Override
  public void method2() {
  }
}
/** 只使用接口中某一个方法的目标类 */
public class SourceSub1 extends Wrapper {
  @Override
  public void method1() {
    System.out.println("This is method1!");
  }
}
/** 另一个只使用接口中某一个方法的目标类 */
public class SourceSub2 extends Wrapper {
  @Override
  public void method2() {
    System.out.println("This is method2!");
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Sourceable source1 = new SourceSub1();
    source1.method1();
    source1.method2();
    Sourceable source2 = new SourceSub2();
    source2.method1();
    source2.method2();
  }
}

结构型模式:装饰模式

简要描述:装饰模式就是给一个对象增加一些新的功能,而且是动态的。实现方法就是装饰器与被装饰对象实现同一个接口,且装饰器持有被装饰对象的实例。

/** 接口类 */
public interface Sourceable {
  public void method();
}
/** 实现类 */
public class Source implements Sourceable {
  @Override
  public void method() {
    System.out.println("This is the original method!");
  }
}
/** 装饰器类 */
public class Decorator implements Sourceable {
  private Sourceable sourceable;
  public Decorator(Sourceable sourceable) {
    this.sourceable = sourceable;
  }
  @Override
  public void method() {
    System.out.println("Before decorator...");
    sourceable.method();
    System.out.println("After decorator...");
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Sourceable sourceable = new Source();
    Decorator decorator = new Decorator(sourceable);
    decorator.method();
  }
}

结构型模式:代理模式

简要描述:代理模式就是多了一个代理类,替原对象处理一些操作。就比如我们租房子的时候去找中介,为什么喃?因为你对该地区房屋信息的掌握不如中介熟悉、全面,我们需要找一个熟悉这些东西的人去帮我们做这些事。

/** 接口,定义一个方法(即要做的事) */
public interface Sourceable {
  public void method();
}
/** 实现类,实现接口中的方法(即具体怎么去做这件事) */
public class Source implements Sourceable {
  @Override
  public void method() {
    System.out.println("This is the original method!");
  }
}
/** 代理类,持有实现类的实例,调用实现类的方法(即帮助客户去找实现类完成这件事) */
public class Proxy implements Sourceable {
  private Source source;
  public Proxy() {
    this.source = new Source();
  }
  @Override
  public void method() {
    before();
    source.method();
    after();
  }
  private void before() {
    System.out.println("Before proxy...");
  }
  private void after() {
    System.out.println("After proxy...");
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Proxy proxy = new Proxy();
    proxy.method();
  }
}

结构型模式:外观模式

简要描述:外观模式就类似于电脑模式,将具体实现功能的东西都包在一个壳子里,用户使用的时候,不会直接接触到壳子里面的东西。比如启动电脑的时候,我们只需要在机箱上按一下启动键,电脑就自动启动了,而不用拆开机箱一个一个地将CPU启动、将内存启动、将硬盘启动等等。

/** CPU动作(开、关) */
public class Cpu {
  public void startup() {
    System.out.println("CPU startup...");
  }
  public void shutdonw() {
    System.out.println("CPU shutdown...");
  }
}
/** 硬盘动作(开、关) */
public class Disk {
  public void startup() {
    System.out.println("Disk startup...");
  }
  public void shutdown() {
    System.out.println("Disk shutdown...");
  }
}
/** 内存动作(开、关) */
public class Memory {
  public void startup() {
    System.out.println("Memory startup...");
  }
  public void shutdown() {
    System.out.println("Memory shutdown...");
  }
}
/** 电脑动作(开、关),该类即为外观类 */
public class Computer {
  private Cpu cpu;
  private Disk disk;
  private Memory memory;
  public Computer() {
    this.cpu = new Cpu();
    this.disk = new Disk();
    this.memory = new Memory();
  }
  public void startup() {
    System.out.println("Start the computer...");
    cpu.startup();
    memory.startup();
    disk.startup();
    System.out.println("Start computer finished...");
  }
  public void shutdown() {
    System.out.println("Shutdown the computer...");
    disk.shutdown();
    memory.shutdown();
    cpu.shutdown();
    System.out.println("Shutdown computer finished...");
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Computer computer = new Computer();
    computer.startup();
    computer.shutdown();
  }
}

结构型模式:桥接模式

简要描述:桥接模式的核心思想就是将抽象与实现解耦,使得二者独立变化。比如JDBC桥DriverManager,JDBC连接数据库的时候,在各个数据库中切换,只需要将配置的驱动类修改一下即可,不需要改动代码,原因就是JDBC提供统一的接口,各个数据库各自提供实现。

/** 总接口 */
public interface Sourceable {
  public void method();
}
/** 第一个实现类 */
public class SourceSub1 implements Sourceable {
  @Override
  public void method() {
    System.out.println("This is SourceSub1's method!");
  }
}
/** 第二个实现类 */
public class SourceSub2 implements Sourceable {
  @Override
  public void method() {
    System.out.println("This is SourceSub2's method!");
  }
}
/** 定义桥。持有接口的实例。 */
public abstract class Bridge {
  private Sourceable sourceable;
  public void method() {
    sourceable.method();
  }
  public Sourceable getSourceable() {
    return sourceable;
  }
  public void setSourceable(Sourceable sourceable) {
    this.sourceable = sourceable;
  }
}
/** 实现桥 */
public class MyBridge extends Bridge {
  @Override
  public void method() {
    getSourceable().method();
  }
}
/** 测试类。可以看到,给桥set不同的驱动,虽然同样的是调用method方法,但实际上却完成了方法调用的转换。 */
public class TestClass {
  public static void main(String[] args) {
    Bridge bridge = new MyBridge();

    Sourceable sourceable1 = new SourceSub1();
    bridge.setSourceable(sourceable1);
    bridge.method();

    Sourceable sourceable2 = new SourceSub2();
    bridge.setSourceable(sourceable2);
    bridge.method();
  }
}

结构型模式:组合模式

简要说明:组合模式有时候又叫“部分-整体”模式,在处理类似树形结构的问题时比较方便。

import java.util.*;
/** 以树形结构为例。TreeNode封装 */
public class TreeNode {
  private String name;
  private TreeNode parent;
  private Vector<TreeNode> children = new Vector<TreeNode>();
  public TreeNode(String name) {
    this.name = name;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public TreeNode getParent() {
    return parent;
  }
  public void setParent(TreeNode parent) {
    this.parent = parent;
  }
  /** 添加子节点 */
  public void add(TreeNode node) {
    node.setParent(this);
    children.add(node);
  }
  /** 删除子节点 */
  public void remove(TreeNode node) {
    children.remove(node);
  }
  /** 获取子节点 */
  public Enumeration<TreeNode> getChildren() {
    return children.elements();
  }
}
import java.util.*;
/**
  测试类。创建根节点root,root下添加a和b,a节点下添加aa,aa节点下添加aaa1和aaa2,b节点下添加bb1和bb2,
  bb1节点下添加bbb节点,getChild方法采用递归方式循环取出所有节点放入map中,并打印出来,之后再把b节
  点下的bb1节点remove掉,再打印出来
  */
public class Test {
  static Map<String, String> map = new HashMap<String, String>();
  public static void main(String[] args) {
    TreeNode root = new TreeNode("root");
    TreeNode a = new TreeNode("a");
    TreeNode aa = new TreeNode("aa");
    TreeNode aaa1 = new TreeNode("aaa1");
    TreeNode aaa2 = new TreeNode("aaa2");
    aa.add(aaa1);
    aa.add(aaa2);
    a.add(aa);
    root.add(a);
    TreeNode b = new TreeNode("b");
    TreeNode bb1 = new TreeNode("bb1");
    TreeNode bb2 = new TreeNode("bb2");
    TreeNode bbb = new TreeNode("bbb");
    bb1.add(bbb);
    b.add(bb1);
    b.add(bb2);
    root.add(b);

    getChild(root.getchildren());
    System.out.println(map.toString());

    map.clear();
    b.remove(bb);
    getChild(root.getChildren());
    System.out.println(map.toString());
  }
  private static TreeNode getChild(Enumeration<TreeNode> e) {
    TreeNode tn = null;
    while(e.hasMoreElements()) {
      TreeNode tn1 = e.nextElement();
      tn = getChild(tn1.getChildren());
      map.put(tn1.getName(), tn1.getParent().getName());
    }
    return tn;
  }
}

结构型模式:享元模式

简要描述:享元模式的主要目的是实现对象的共享,即共享池,通常与工厂模式一起使用。此处我用JDBC连接池来举例。

import java.sql.*;
/** 连接数据库工具类(需要导入MySQL数据库的驱动jar包,我用的是mysql-connector-java-5.0.4.jar) */
public class DbUtil {
  //这里为了减小示例展示的复杂度,就不单独使用配置文件来配置数据库的连接参数了,直接写死到代码里了
  private static String username = "root";
  private static String password = "123456";
  private static String url = "jdbc:mysql://127.0.0.1:3306/jason_test";
  private static String driverClass = "com.mysql.jdbc.Driver";
  static {
    try {
      Class.forName(driverClass);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public static Connection getConn() {
    Connection conn = null;
    try {
      conn = DriverManager.getConnection(url, username, password);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
import java.util.*;
import java.sql.*;
/** 连接池(单例) */
public class DbPool {
  private static final int POOL_SIZE = 100;
  private Vector<Connection> pool = null;
  private DbPool() {
    pool = new Vector<Connection>(POOL_SIZE);
    for (int i = 0; i < POOL_SIZE; i++) {
      pool.add(DbUtil.getConn());
    }
  }
  private static class DbPoolFactory {
    private static DbPool dbPool = new DbPool();
  }
  public static final DbPool getInstance() {
    return DbPoolFactory.dbPool;
  }
  /** 释放数据库链接。实际上是将连接放回到连接池,并不是将其关闭。 */
  public synchronized void release(Connection conn) {
    pool.add(conn);
    System.out.println("释放后连接池中剩余的连接数:" + pool.size());
  }
  /** 从连接池中获取数据库连接 */
  public synchronized Connection getConn() {
    Connection conn = null;
    if (pool.size > 0) {
      conn = pool.get(0);
      pool.remove(conn);
      System.out.println("获取后连接池中剩余的连接数:" + pool.size());
    }
    return conn;
  }
}
import java.sql.*;
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    DbPool pool = DbPool.getInstance();
    Connection conn1 = pool.getConn();
    System.out.println("从连接池中获取到的连接:" + conn1);
    Connection conn2 = pool.getConn();
    System.out.println("从连接池中获取到的连接:" + conn2);
    pool.release(conn1);
  }
}

行为型模式:策略模式

简要描述:策略模式定义了一系列算法,并将每个算法封装起来,使它们可以互相替换,且算法的变化不会影响到使用算法的客户。策略模式的决定权在用户,系统本身提供不同算法的实现,因此,策略模式多用在算法决策系统中,外部用户只需要决定使用哪个算法即可。

/** 算法总接口 */
public interface ICalculator {
  public Integer calculate(int a, int b);
}
/** 加法运算 */
public class Plus implements ICalculator {
  @Override
  public Integer calculate(int a, int b) {
    return a + b;
  }
}
/** 减法运算 */
public class Minus implements ICalculator {
  @Override
  public Integer calculate(int a, int b) {
    return a - b;
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    ICalculator plus = new Plus();
    System.out.println(plus.calculate(3, 5));
    ICalculator minus = new Minus();
    System.out.println(minus.calculate(8, 2));
  }
}

行为型模式:模板方法模式

简要描述:一个抽象类中定义一个主方法,还有N个抽象或实际方法,用子类继承该抽象类,重写抽象方法,通过调用抽象类的主方法,实现对子类重写的抽象方法的调用。

/** 抽象类 */
public abstract class AbstractCalculator {
  public Integer invoke(int a, int b) {
    return calculate(a, b);
  }
  public abstract Integer calculate(int a, int b);
}
/** 加法运算 */
public class Plus extends AbstractCalculator {
  @Override
  public Integer calculate(int a, int b) {
    return a + b;
  }
}
/** 减法运算 */
public class Minus extends AbstractCalculator {
  @Override
  public Integer calculate(int a, int b) {
    return a - b;
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    AbstractCalculator ac1 = new Plus();
    System.out.println(ac1.invoke(3, 5));
    AbstractCalculator ac2 = new Minus();
    System.out.println(ac2.invoke(10, 4));
  }
}

行为型模式:观察者模式

简要描述:当一个对象发生变化时,其他依赖该对象的对象都需要收到通知,这时就需要用到观察者模式。举个例子,当你订阅了某文章,当该文章有后续更新时,你需要能及时通知你,这时就需要观察者模式。在代码中比较容易理解:

/** 观察者总接口 */
public interface Observer {
  public void update();
}
/** 第一个观察者类 */
public class Observer1 implements Observer {
  @Override
  public void update() {
    System.out.println("观察者1收到通知!");
  }
}
/** 第二个观察者 */
public class Observer2 implements Observer {
  @Override
  public void update() {
    System.out.println("观察者2收到通知!");
  }
}
/** 行为总接口 */
public interface Subject {
  /** 增加观察者 */
  public void add(Observer observer);
  /** 删除观察者 */
  public void delete(Observer observer);
  /** 通知所有观察者 */
  public void notifyObservers();
  /** 自身的行为 */
  public void operation();
}
import java.util.*
/** 定义一个抽象类,实现对观察者对象的操作(增、删、通知) */
public abstract class AbstractSubject implements Subject {
  private Vector<Observer> vector = new Vector<Observer>();
  @Override
  public void add(Observer observer) {
    vector.add(observer);
  }
  @Override
  public void delete(Observer observer) {
    vector.remove(observer);
  }
  @Override
  public void notifyObservers() {
    Enumeration<Observer> e = vector.elements();
    while(e.hasMoreElements()) {
      e.nextElement().update();
    }
  }
  @Override
  public void operation() {
  }
}
/** 行为实现类(即做什么事的时候发通知) */
public class MySubject extends AbstractSubject {
  @Override
  public void operation() {
    System.out.println("文章更新了。。。");
    notifyObservers();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Subject sub = new MySubject();
    Observer observer1 = new Observer1();
    Observer observer2 = new Observer2();
    sub.add(observer1);
    sub.add(observer2);
    sub.operation();
    sub.delete(observer1);
    sub.operation();
  }
}

行为型模式:迭代器模式

简要描述:迭代器模式又叫做游标模式,就是顺序访问遍历的对象。

/** 迭代器接口 */
public interface Iterator {
  /** 上一个 */
  public Object previous();
  /** 下一个 */
  public Object next();
  /** 是否还有下一个 */
  public boolean hasNext();
  /** 获取第一个 */
  public Object first();
}
/** 集合接口 */
public interface Collection {
  /** 集合遍历 */
  public Iterator iterator();
  /** 获取元素 */
  public Object get(int i);
  /** 集合的大小 */
  public int size();
  /** 向集合中添加对象 */
  public void add(Object o);
}
/** 迭代器实现 */
public class MyIterator implements Iterator {
  private Collection collection;
  private int pos = -1;
  public MyIterator(Collection collection) {
    this.collection = collection;
  }
  @Override
  public Object previous() {
    if (pos > 0) {
      pos--;
    }
    return collection.get(pos);
  }
  @Override
  public Object next() {
    if (pos < collection.size() - 1) {
      pos++;
    }
    return collection.get(pos);
  }
  @Override
  public boolean hasNext() {
    if (pos < collection.size() - 1) {
      return true;
    }
    return false;
  }
  @Override
  public Object first() {
    if (collection.size() > 0) {
      return collection.get(0);
    }
    return null;
  }
}
import java.util.Vector;
/** 集合实现类 */
public class MyCollection implements Collection {
  private transient Vector<Object> vector;
  public MyCollection() {
    vector = new Vector<Object>();
  }
  @Override
  public Iterator iterator() {
    return new MyIterator(this);
  }
  @Override
  public Object get(int i) {
    return vector.get(i);
  }
  @Override
  public int size() {
    return vector.size();
  }
  @Override
  public void add(Object o) {
    vector.add(o);
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Collection c = new MyCollection();
    c.add("A");
    c.add("B");
    c.add("C");
    Iterator it = collection.iterator();
    while(it.hasNext()) {
      System.out.println(it.next());
    }
  }
}

行为型模式:责任链模式

简要描述:有多个对象,每个对象都持有下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终哪个对象会处理该请求,所以,责任链模式可以实现“在隐瞒客户端的情况下,对系统进行动态调整”。

/** 处理行为的接口 */
public interface Handler {
  public void operator();
}
/** 抽象类 */
public abstract class AbstractHandler {
  private Handler handler;
  public Handler getHandler() {
    return handler;
  }
  public void setHandler(Handler handler) {
    this.handler = handler;
  }
}
/** 处理行为的实现类 */
public class MyHandler extends AbstractHandler implements Handler {
  private String name;
  public MyHandler(String name) {
    this.name = name;
  }
  @Override
  public void operator() {
    System.out.println(name + " deal!");
    Handler handler = getHandler();
    if (null != handler) {
      handler.operator();
    }
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    MyHandler mh1 = new MyHandler("mh1");
    MyHandler mh2 = new MyHandler("mh2");
    MyHandler mh3 = new MyHandler("mh3");
    mh1.setHandler(mh2);
    mh2.setHandler(mh3);
    mh1.operator();
  }
}

行为型模式:命令模式

简要描述:命令模式我用个例子来助于理解,司令员下令让士兵去干件事情,从事件事情来考虑,司令员的作用就是发出口令,口令经过传递,到了士兵耳朵里,士兵去执行。这个过程的好处就在于两者互相解耦,任何一方都不用去依赖他人,只需要做好自己的事情就行了,司令员要的是结果,不会关注士兵怎么去实现它。所以命令模式的目的就是达到命令的发出者与执行者之前解耦,实现请求与执行分开。

/** 执行者(士兵) */
public class Receiver {
  public void action() {
    System.out.println("Command received!");
  }
}
/** 命令接口 */
public interface Command {
  public void exec();
}
/** 命令实现类 */
public class MyCommand implements Command {
  private Receiver receiver;
  public MyCommand(Receiver receiver) {
    this.receiver = receiver;
  }
  @Override
  public void exec() {
    receiver.action();
  }
}
/** 命令发出者(司令员) */
public class Invoker {
  private Command command;
  public Invoker(Command command) {
    this.command = command;
  }
  public void action() {
    command.exec();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Receiver receiver = new Receiver();
    Command command = new MyCommand(receiver);
    Invoker invoker = new Invoker(command);
    invoker.action();
  }
}

行为型模式:备忘录模式

简要描述:备忘录模式的主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象。

/** 备忘录类 */
public class Memento {
  private String value;
  public Memento(String value) {
    this.value = value;
  }
  public String getValue() {
    return value;
  }
  public void setValue(String value) {
    this.value = value;
  }
}
/** 保存备忘录的类 */
public class Storage {
  private Memento memento;
  public Storage(Memento memento) {
    this.memento = memento;
  }
  public Memento getMemento() {
    return memento;
  }
  public void setMemento(Memento memento) {
    this.memento = memento;
  }
}
/** 原始类(需要被保存某个状态的类) */
public class Original {
  private String value;
  public Original(String value) {
    this.value = value;
  }
  public String getValue() {
    return value;
  }
  public void setValue(String value) {
    this.value = value;
  }
  public Memento createMemento() {
    return new Memento(value);
  }
  public void restoreMemento(Memento memento) {
    this.value = memento.getValue();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    //创建原始类
    Original original = new Original("egg");
    //创建备忘录
    Storage storage = new Storage(original.createMemento());
    System.out.println("初始化的状态为:" + original.getValue());
    original.setValue("milk");
    System.out.println("修改后的状态为:" + original.getValue());
    original.restoreMemento(storage.getMemento());
    System.out.println("恢复后的状态为:" + original.getValue());
  }
}

行为型模式:状态模式

简要描述:当对象的状态改变时,同时改变其行为。比如QQ有离线、忙碌、在线、隐身几种状态,每种状态对应着不同的操作。

/** 状态类 */
public class State {
  private String value;
  public String getValue() {
    return value;
  }
  public void setValue(String value) {
    this.value = value;
  }
  public void method1() {
    System.out.println("This is the first state!");
  }
  public void method2() {
    System.out.println("This is the second state!");
  }
}
/** 改变状态的类 */
public class Context {
  private State state;
  public Context(State state) {
    this.state = state;
  }
  public State getState() {
    return state;
  }
  public void setState(State state) {
    this.state = state;
  }
  public void method() {
    if ("state1".equals(this.state.getValue())) {
      this.state.method1();
    } else if ("state2".equals(this.state.getValue())) {
      this.state.method2();
    }
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    State state = new State();
    Context context = new Context(state);
    //设置第一种状态
    state.setValue("state1");
    context.method();
    //设置第二种状态
    state.setValue("state2");
    context.method();
  }
}

行为型模式:访问者模式

简要描述:访问者模式就是一种分离对象数据结构与行为的方法,通过这种分离,可以达到为一个被访问者动态添加新的操作而无需做其他的修改的效果。但是,若系统数据结构易于变化,则不适合用访问者模式。访问者模式的优点就是增加操作很容易,因为增加操作意味着增加新访问者。

/** 被访问者接口 */
public interface Subject {
  public void accept(Visitor visitor);
  public String getSubject();
}
/** 被访问者实现类 */
public class MySubject implements Subject {
  @Override
  public void accept(Visitor visitor) {
    visitor.visit(this);
  }
  @Override
  public String getSubject() {
    return "love";
  }
}
/** 访问者接口 */
public interface Visitor {
  public void visit(Subject subject);
}
/** 访问者实现类 */
public class MyVisitor implements Visitor {
  @Override
  public void visit(Subject subject) {
    System.out.println("Visit the subject: " + subject.getSubject());
  }
}
/**
  测试类(此处我只添加了一个访问者,如需要再增加操作,可以添加多个访问者,而原对象不需要做任何操作,且原
  对象数据结构不能改变)
  */
public class TestClass {
  public static void main(String[] args) {
    Visitor visitor = new MyVisitor();
    Subject subject = new MySubject();
    subject.accept(visitor);
  }
}

行为型模式:中介者模式

简要描述:中介者模式是用来降低类与类之间的耦合度的。如果类与类之前有依赖关系的话,不利于功能的扩展和维护,只要修改一个对象,其他关联的对象都得进行修改。如果使用中介者模式,只需要关心与中介者类的关系,具体类与类之间的关系与调度交给中介者类就行了。这有点像Spring容器的作用。从理论上来讲的话,与上面说到的代理模式和命令模式有点类似,实际情况我们从代码里面来看:

/** 中介者接口 */
public interface Mediator {
  public void createMediator();
  public void workAll();
}
/** 有关联的两个类的总抽象 */
public abstract class User {
  private Mediator mediator;
  public User(Mediator mediator) {
    this.mediator = mediator;
  }
  public Mediator getMediator() {
    return mediator;
  }
  public abstract void work();
}
/** 类1 */
public class User1 extends User {
  public User1(Mediator mediator) {
    super(mediator);
  }
  @Override
  public void work() {
    System.out.println("This is User1's work!");
  }
}
/** 类2 */
public class User2 extends User {
  public User2(Mediator mediator) {
    super(mediator);
  }
  @Override
  public void work() {
    System.out.println("This is User2's work!");
  }
}
/** 中介者实现类(实现两个类解耦) */
public class MyMediator implements Mediator {
  private User1 user1;
  private User2 user2;
  public User1 getUser1() {
    return user1;
  }
  public User2 getUser2() {
    return user2;
  }
  @Override
  public void createMediator() {
    user1 = new User1(this);
    user2 = new User2(this);
  }
  @Override
  public void workAll() {
    user1.work();
    user2.work();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    Mediator mediator = new MyMediator();
    mediator.createMediator();
    mediator.workAll();
  }
}

行为型模式:解释器模式

简要描述:解释器模式用来做各种各样的解释器,例如正则表达式的解释器等等。它一般应用在OOP开发中的编译器开发,所以使用面比较窄。

/** 上下文类 */
public class Context {
  private int num1;
  private int num2;
  public Context(int num1, int num2) {
    this.num1 = num1;
    this.num2 = num2;
  }
  public int getNum1() {
    return num1;
  }
  public void setNum1(int num1) {
    this.num1 = num1;
  }
  public int getNum2() {
    return num2;
  }
  public void setNum2(int num2) {
    this.num2 = num2;
  }
}
/** 解释器接口 */
public interface Expression {
  public int interpret(Context context);
}
/** 减法运算处理类 */
public class Minus implements Expression {
  @Override
  public int interpret(Context context) {
    return context.getNum1() - context.getNum2();
  }
}
/** 乘法运算处理类 */
public class Multiply implements Expression {
  @Override
  public int interpret(Context context) {
    return context.getNum1() * context.getNum2();
  }
}
/** 加法运算处理类 */
public class Plus implements Expression {
  @Override
  public int interpret(Context context) {
    return context.getNum1() + context.getNum2();
  }
}
/** 测试类 */
public class TestClass {
  public static void main(String[] args) {
    //最终计算(9+8-2)*3-3+11的结果
    //计算9+8的结果
    int n1 = new Plus().interpret(new Context(9, 8));
    //计算9+8-2的结果
    int n2 = new Minus().interpret(new Context(n1, 2));
    //计算(9+8-2)*3的结果
    int n3 = new Multiply().interpret(new Context(n2, 3));
    //计算(9+8-2)*3-3的结果
    int n4 = new Minus().interpret(new Context(n3, 3));
    //计算(9+8-2)*3-3+11的结果
    int n5 = new Plus().interpret(new Context(n4, 11));
    System.out.println("(9+8-2)*3-3+11=" + n5);
  }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值