Java学习------设计模式(1)
设计模式是软件开发中针对常见问题的可重用解决方案,是最佳实践的总结。其分为3大类:
创建型模式;其关注对象创建机制,主要有单例,工厂方法,抽象工厂,建造者,原型这五种;
结构型模式:以处理类和对象的组合为主,主要有适配器,桥接,组合,装饰器,外观,享元,代理这七种;
行为型模式:主要关注对象间的通信,有责任链,命令,解释器,迭代器,中介者,备忘录,观察者,状态,策略,模板方法,访问者这11种。
但不管是哪一种设计模式,其核心目的都是为了减少代码复用,提升代码的可维护性和可扩展性,实现代码的标准化,吸收成功的经验,避免出现以前出现过的错误,实现最佳实践。本文就单例,抽象工厂,适配器,代理这四个设计模式详细展开。
单例模式是最简单设计模式之一,这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象,也就是说不能使用new关键字来创建对象。其核心特性主要有3:
public class EagerSingleton {//饿汉式// 类加载时就初始化private static final EagerSingleton INSTANCE = new EagerSingleton();// 私有构造器private EagerSingleton() {}public static EagerSingleton getInstance() {return INSTANCE;}
}//此模式线程安全,但是可能造成资源浪费public class UnsafeLazySingleton {//懒汉式(基础版本)private static UnsafeLazySingleton instance;private UnsafeLazySingleton() {}public static UnsafeLazySingleton getInstance() {if (instance == null) {instance = new UnsafeLazySingleton();}return instance;}
}//此模式线程不安全public class SynchronizedLazySingleton {//懒汉式(采用同步方式)private static SynchronizedLazySingleton instance;private SynchronizedLazySingleton() {}public static synchronized SynchronizedLazySingleton getInstance() {if (instance == null) {instance = new SynchronizedLazySingleton();}return instance;}
}//此模式线程安全但是效率较低
抽象工厂模式是最常用的创建型设计模式,它提供了一种创建相关或依赖对象族的接口,而无需指定它们的具体类。其主要有4大部分:
抽象工厂:声明创建产品族中各个产品的方法
具体工厂:实现抽象工厂接口,创建具体产品
抽象产品:声明产品接口
具体产品:实现抽象产品接口的具体类
其主要关注的是可以生产的产品族(如a族,b族,c族等),可以轻松的添加和切换生产的产品族,
// 产品A接口
interface ProductA {void use();
}// 产品B接口
interface ProductB {void operate();
}//具体实现
// 产品A的型号1
class ProductA1 implements ProductA {@Overridepublic void use() {System.out.println("使用A1型产品");}
}// 产品A的型号2
class ProductA2 implements ProductA {@Overridepublic void use() {System.out.println("使用A2型产品");}
}// 产品B的型号1
class ProductB1 implements ProductB {@Overridepublic void operate() {System.out.println("操作B1型产品");}
}// 产品B的型号2
class ProductB2 implements ProductB {@Overridepublic void operate() {System.out.println("操作B2型产品");}
}
//定义抽象工厂接口
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}
//实现具体工厂
// 生产第一套产品(A1+B1)
class Factory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ProductA1();}@Overridepublic ProductB createProductB() {return new ProductB1();}
}// 生产第二套产品(A2+B2)
class Factory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ProductA2();}@Overridepublic ProductB createProductB() {return new ProductB2();}
}
//客户端使用
public class Client {public static void main(String[] args) {// 使用第一套工厂生产产品AbstractFactory factory1 = new Factory1();ProductA a1 = factory1.createProductA();ProductB b1 = factory1.createProductB();a1.use(); // 输出: 使用A1型产品b1.operate(); // 输出: 操作B1型产品System.out.println("------");// 使用第二套工厂生产产品AbstractFactory factory2 = new Factory2();ProductA a2 = factory2.createProductA();ProductB b2 = factory2.createProductB();a2.use(); // 输出: 使用A2型产品b2.operate(); // 输出: 操作B2型产品}
}
适配器模式是一种结构型设计模式,它允许不兼容的接口能够一起工作。适配器模式就像现实世界中的电源适配器,让不同规格的插头能够插入插座。其通过包装对象的方式,将一个类的接口转换成客户端期望的另一个接口,从而使原本因接口不兼容而无法一起工作的类可以协同工作。
适配器模式主要有三种角色:
目标接口:客户端期望的接口
适配者:需要被适配的现有类
适配器:包装适配者并实现目标接口
其实现代码如下:
//类适配器(通过继承实现)
// 目标接口
interface Target {void request();
}// 需要适配的类
class Adaptee {public void specificRequest() {System.out.println("Adaptee的特殊请求");}
}// 类适配器(继承Adaptee并实现Target)
class ClassAdapter extends Adaptee implements Target {@Overridepublic void request() {specificRequest(); // 调用父类方法}
}// 客户端使用
public class Client {public static void main(String[] args) {Target target = new ClassAdapter();target.request(); // 输出: Adaptee的特殊请求}
}//对象适配器(通过组合实现)
// 目标接口
interface Target {void request();
}// 需要适配的类
class Adaptee {public void specificRequest() {System.out.println("Adaptee的特殊请求");}
}// 对象适配器(组合Adaptee并实现Target)
class ObjectAdapter implements Target {private Adaptee adaptee;public ObjectAdapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}// 客户端使用
public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new ObjectAdapter(adaptee);target.request(); // 输出: Adaptee的特殊请求}
}
其优点众多,包括复用性强,可以实现多个不兼容的类一起工作,使用灵活且方便,同时还能降低程序的耦合度,遵循开闭原则,通过引入新的适配器进行适配而不是修改源代码。但是如果其会带来一些额外的开销,同时由于增加了新的类和对象,会提高程序的复杂度。
最后是代理模式,其是一种结构型设计模式,为其他对象提供一种代理以控制对这个对象的访问。代理模式就像现实生活中的"中介",在客户端和目标对象之间起到中介作用。其主要是通过创建一个代理对象来控制对原始对象的访问,可以在不改变原始类代码的情况下,增加额外的功能或控制访问。主要实现4大功能:
访问控制:控制对原始对象的访问权限
功能增强:在不修改原始对象的情况下添加额外功能
延迟初始化:推迟高开销对象的创建
远程访问:为远程对象提供本地代表
其主要包含3大角色,分别是:
抽象主题:定义真实主题和代理主题的共同接口
真实主题:实际执行业务逻辑的对象
代理:持有真实主题的引用,控制对真实主题的访问
其有多种实现方式,具体代码如下:
//1.静态代理
/***手动编写代理类 *一个真实主题对应一个代理类*编译时确定代理关系
*/
// 抽象主题
interface Image {void display();
}// 真实主题
class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename = filename;loadFromDisk();}private void loadFromDisk() {System.out.println("加载图片: " + filename);}@Overridepublic void display() {System.out.println("显示图片: " + filename);}
}// 代理
class ProxyImage implements Image {private RealImage realImage;private String filename;public ProxyImage(String filename) {this.filename = filename;}@Overridepublic void display() {if (realImage == null) {realImage = new RealImage(filename); // 延迟初始化}preDisplay();realImage.display();postDisplay();}private void preDisplay() {System.out.println("显示前准备工作");}private void postDisplay() {System.out.println("显示后清理工作");}
}// 客户端使用
public class Client {public static void main(String[] args) {Image image = new ProxyImage("test.jpg");// 图片直到真正需要显示时才会加载image.display();}
}//2.jdk动态代理/***运行时动态生成代理类*只能代理接口*通过InvocationHandler统一处理所有方法调用
*/
import java.lang.reflect.*;// 抽象主题
interface UserService {void addUser(String name);void deleteUser(String name);
}// 真实主题
class UserServiceImpl implements UserService {@Overridepublic void addUser(String name) {System.out.println("添加用户: " + name);}@Overridepublic void deleteUser(String name) {System.out.println("删除用户: " + name);}
}// 调用处理器
class UserServiceInvocationHandler implements InvocationHandler {private Object target;public UserServiceInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("--- 开始执行 " + method.getName() + " ---");Object result = method.invoke(target, args);System.out.println("--- 结束执行 " + method.getName() + " ---");return result;}
}// 客户端使用
public class Client {public static void main(String[] args) {UserService realService = new UserServiceImpl();UserService proxy = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(),new Class[]{UserService.class},new UserServiceInvocationHandler(realService));proxy.addUser("张三");proxy.deleteUser("李四");}
}//3.CGLIB动态代理
/***通过继承方式实现代理*可以代理普通类(不需要接口)*性能通常比JDK动态代理好*不能代理final类和方法*/
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;// 真实主题(不需要实现接口)
class ProductService {public void addProduct(String name) {System.out.println("添加产品: " + name);}public void deleteProduct(String name) {System.out.println("删除产品: " + name);}
}// 方法拦截器
class ProductServiceInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println(">>> 调用前: " + method.getName());Object result = proxy.invokeSuper(obj, args);System.out.println("<<< 调用后: " + method.getName());return result;}
}// 客户端使用
public class Client {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(ProductService.class);enhancer.setCallback(new ProductServiceInterceptor());ProductService proxy = (ProductService) enhancer.create();proxy.addProduct("手机");proxy.deleteProduct("电脑");}
}