开发模式
Java 中一般认为有23种设计模式,当然暂时不需要所有的都会,但是其中常见的几种设计模式应该去掌握。
【一】总体来说设计模式分为三大类:
创建型模式,共五种:
- 工厂方法模式
- 抽象工厂模式
- 单例模式
- 建造者模式
- 原型模式。
结构型模式,共七种:
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
- 桥接模式
- 组合模式
- 享元模式。
行为型模式,共十一种:
- 策略模式
- 模板方法模式
- 观察者模式
- 迭代子模式
- 责任链模式
- 命令模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式。
【二】单例模式
所谓的单例设计指的是一个类只允许产生一个实例化对象。 最好理解的一种设计模式,分为懒汉式和饿汉式。
- 1、饿汉式:构造方法私有化,外部无法产生新的实例化对象,只能通过static方法取得实例化对象
class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
- 2、懒汉式:当第一次去使用Singleton对象的时候才会为其产生实例化对象的操作
class Singleton {
private static volatile Singleton singleton = null;
private Singleton() {
}
//双重检验
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
当多个线程并发执行 getInstance 方法时,懒汉式会存在线程安全问题,所以用到了 synchronized 来实现线程的同步,当一个线程获得锁的时候其他线程就只能在外等待其执行完毕。
【三】工厂设计模式
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();
}
}
【四】代理模式
代理模式指给一个对象提供一个代理对象,并由代理对象控制对原对象的引用。代理可以分为静态代理和动态代理
1、静态代理
interface IService {
void service();
}
class Service implements IService{
@Override
public void service() {
System.out.println("被代理对象执行相关操作");
}
}
class ProxyService implements IService{
private IService service;
public ProxyService() {
this.service = new Service();
}
public ProxyService(IService service) {
this.service = service;
}
@Override
public void service() {
System.out.println("开始执行service()方法");
service.service();
System.out.println("service()方法执行完毕");
}
}
2、动态代理
- JDK动态代理:
创建动态代理对象的步骤:
- 指明一系列的接口来创建一个代理对象
- 创建一个调用处理器(InvocationHandler)对象
- 将这个代理指定为某个其他对象的代理对象
- 在调用处理器的invoke()方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要的操作
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 ProxyTest {
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();
}
}
- CGlib动态代理:
利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
interface IService {
void service();
}
class Service implements IService{
@Override
public void service() {
System.out.println("被代理对象执行相关操作");
}
}
/**
* CGlib动态代理类
*/
public class CGLibProxy implements MethodInterceptor {
// CGlib需要代理的目标对象
private Object targetObject;
public Object createProxyObject(Object obj) {
this.targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
return proxyObj;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object obj = null;
// 过滤方法
if ("addUser".equals(method.getName())) {
// 检查权限
checkPopedom();
}
obj = method.invoke(targetObject, args);
return obj;
}
private void checkPopedom() {
System.out.println("检查权限:checkPopedom()!");
}
}
public class ProxyTest {
public static void main(String[] args) {
IService service = new Service();
IService proxyService = (IService) new CGLibProxy().createProxyObject(new Service());
proxyService.service();
}
}
【五】策略模式
将算法的责任和本身进行解耦,使得:
- 算法可独立于使用外部而变化
- 客户端方便根据外部条件选择不同策略来解决不同问题
我们举一个销售策略的例子,在不同的时节,需要使用不同的销售方式,因此定义如下:
// 定义接口方法
public abstract class Strategy {
public abstract void show();
}
//为春节准备的促销活动A
class StrategyA extends Strategy{
@Override
public void show() {
System.out.println("为春节准备的促销活动A");
}
}
//为中秋节准备的促销活动B
class StrategyB extends Strategy{
@Override
public void show() {
System.out.println("为中秋节准备的促销活动B");
}
}
//为圣诞节准备的促销活动C
class StrategyC extends Strategy{
@Override
public void show() {
System.out.println("为圣诞节准备的促销活动C");
}
}
public class SalesMan {
//持有抽象策略角色的引用
private Strategy strategy;
//生成销售员实例时告诉销售员什么节日(构造方法)
//使得让销售员根据传入的参数(节日)选择促销活动(这里使用一个简单的工厂模式)
public SalesMan(String festival) {
switch ( festival) {
//春节就使用春节促销活动
case "A":
strategy = new StrategyA();
break;
//中秋节就使用中秋节促销活动
case "B":
strategy = new StrategyB();
break;
//圣诞节就使用圣诞节促销活动
case "C":
strategy = new StrategyC();
break;
}
}
//向客户展示促销活动
public void SalesManShow(){
strategy.show();
}
}
【六】观察者模式
观察者模式使用三个类 Subject、Observer 和 Client。
Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。
1、创建 Subject 类。
2、创建 Observer 类。
3、创建实体观察者类
4、使用 Subject 和实体观察者对象。
【七】链接
https://blog.csdn.net/XSL1990/article/details/16359289
https://blog.csdn.net/qq_38024548/article/details/80480831
https://blog.csdn.net/qq_25827845/article/details/52932234
https://blog.csdn.net/ljh0302/article/details/81562415
https://wenku.baidu.com/view/13354aabf021dd36a32d7375a417866fb84ac077.html
https://wenku.baidu.com/view/e7b1620b51e79b896902265f.html
设计模式常见的面试题
设计模式面试题