Java面试--设计模式

设计模式

单例模式【Singleton】

定义:确保全局最多只有一个对象

适用:构建缓慢的对象;需要统一管理的资源

优点:1.减少内存的占用
           2.单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
           3.因为类控制了实例化过程,所以类可以灵活更改实例化过程   

缺点:1.很多全局状态 2. 线程安全性问题

创建:

1.双重锁模式【详解】

 将同步内容下放到if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了

2.作为 Java 类的静态变量

3.使用框架提供的能力

变继承关系为组合关系

继承关系

1.描述 is-a 的关系

2.不要用继承关系来实现复用,要使用设计模式来实现复用

例 将Employee 变为 Manager

代码:state(状态)模式【详解】

Role.java

package interview.designpattern.company;

public interface Role {
  void doWork();
}

Engineer.java

package interview.designpattern.company;

public class Engineer implements Role {

  @Override
  public void doWork() {
    System.out.println("Doing engineer work.");
  }

  @Override
  public String toString() {
    return "Engineer";
  }
}

Employee.java

package interview.designpattern.company;

import java.util.List;
import java.util.Objects;

public class Employee {
  public static List<Employee> allEmployees;

  private final String name;
  private final int salary;
  private Role role;

  public Employee(String name, int salary, Role role) {
    this.name = name;
    this.salary = salary;
    this.role = role;
  }

  public void doWork() {	//新增代码
    role.doWork();
  }

  public void getPaid(BankEndPoint bank) {
    bank.payment(name, salary);
  }

  // Package private for logic in the package to control
  // when employees are loaded.
  static void loadAllEmployees() {
    // Loads all employees from database.
  }

  @Override
  public int hashCode() {
    return Objects.hash(name, salary, role);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    Employee other = (Employee) obj;	//新增代码
    return Objects.equals(this.name, other.name)
        && Objects.equals(this.salary, other.salary)
        && Objects.equals(this.role, other.role);
  }

  @Override
  public String toString() {
    return "Employee [name=" + name
        + ", salary=" + salary
        + ", role=" + role + "]";
  }

  public String getName() {
    return name;
  }

  public int getSalary() {
    return salary;
  }

  public Role getRole() {//新增代码
    return role;
  }

  public void setRole(Role role) {//新增代码
    this.role = role;
  }
}

Tester.java

package interview.designpattern.company;

import java.util.Arrays;
import java.util.LinkedList;

public class Tester {
  public static void main(String[] args) {
    Employee employee1 = new Employee("John", 10000,
        new Engineer());
    Employee employee2 = new Employee("Mary", 20000,
        new Engineer());

    LinkedList<Employee> employees = new LinkedList<>();
    employees.add(employee1);
    employees.add(employee2);

    System.out.println("Print using for each");
    for (Employee employee : employees) {
      System.out.println(employee);
    }

    System.out.println("Testing managers");
    employee2.setRole(new Manager(Arrays.asList(employee1)));
    for (Employee employee : employees) {
      System.out.println(employee);
    }

    System.out.println("Testing doWork");
    System.out.println("Employee1");
    employee1.doWork();
    System.out.println("Employee2");
    employee2.doWork();
  }
}

输出:

 Decorator模式【详解】

装饰(Decorator)模式又名包装(Wrapper)模式。装饰模式以对客户端透明 的方式扩展对象的功能,是继承关系的一个替代方案。

    装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式使用原来被装饰的类的一个子类的实例,把客户端的调用委派到被装饰类。关键在于这种扩展是完全透明的。与生成子类相比,它更具有灵活性。

LogginRunnable 和 CodingTask 都要满足 Runnable 接口

CodingTask  是真正做事的,LogginRunnable  是装饰

代码:LoggingRunnable.java

package interview.designpattern.task;

public class LoggingRunnable implements Runnable {

  private final Runnable innerRunnable;

  public LoggingRunnable(Runnable innerRunnable) {
    this.innerRunnable = innerRunnable;
  }

  @Override
  public void run() {
    long startTime = System.currentTimeMillis();
    System.out.println("Task started at "
        + startTime);

    innerRunnable.run();

    System.out.println("Task finished. Elapsed time: "
        + (System.currentTimeMillis() - startTime));
  }
}

CodingTask.java

package interview.designpattern.task;

public class CodingTask implements Runnable {

  private final int employeeId;

  public CodingTask(int employeeId) {
    this.employeeId = employeeId;
  }

  @Override
  public void run() {
    System.out.println("Employee " + employeeId
        + " started writing code.");

    try {
      Thread.sleep(5000);
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }

    System.out.println("Employee " + employeeId
        + " finished writing code.");
  }
}

TransactionalRunnable.java

package interview.designpattern.task;

public class TransactionalRunnable implements Runnable {

  private final Runnable innerRunnable;

  public TransactionalRunnable(Runnable innerRunnable) {
    this.innerRunnable = innerRunnable;
  }

  @Override
  public void run() {
    boolean shouldRollback = false;
    try {
      beginTransaction();
      innerRunnable.run();
    } catch (Exception e) {
      shouldRollback = true;
      throw e;
    } finally {
      if (shouldRollback) {
        rollback();
      } else {
        commit();
      }
    }
  }

  private void commit() {
    System.out.println("commit");
  }

  private void rollback() {
    System.out.println("rollback");
  }

  private void beginTransaction() {
    System.out.println("beginTransaction");
  }
}

Tester.java

package interview.designpattern.task;

public class Tester {

  public static void main(String[] args) {
    new LoggingRunnable(
        new TransactionalRunnable(
            new CodingTask(0))).run();
  }
}

输出:

如何创建对象

使用 new 来创建的缺点:

1.编译时必须决定创建那个类的对象

2.参数意义不明确

解决方法:

抽象工厂(Abstract Factory)模式【详解】

抽象工厂模式(Abstract Factory Pattern)是一种比较常用的模式,其定义如下:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes. 即为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。它的通用类图如下:

1)封装性。每个产品的实现类不是高层模块要关心的,它要关心的是接口,是抽象,它不关心对象是如何创建出来的,这都由工厂类负责的,只要知道工厂类是谁,我就能创建一个需要的对象,省时省力。

  2)产品族内的约束为非公开状态。例如生产男女比例的问题上,猜想女娲娘娘肯定有自己的打算,那么在抽象工厂模式中,这些约束都在工厂内里面实现的。

缺点

        抽象工厂模式最大的缺点就是产品族扩展非常困难。如果我们要增加一个产品C,也就是说产品族由原来的A和B增加到3个,那么我们首先要在抽象类AbstractCreator中增加createProductC()方法,然后两个实现类都要修改……说到这里,已经知道了扩展的弊端了……

        注意这里是产品族扩展比较困难,而不是产品等级扩展困难。产品等级扩展还是非常容易的,增加一个产品等级,只要增加一个工厂类负责新增加出来的产品生产任务即可。也就是说横向扩展容易,纵向扩展难。

猜你喜欢

转载自blog.csdn.net/jianghao233/article/details/82858640
今日推荐