设计模式
一、创建型模式
1.原型模式
动机
在软件系统种,经常存在着某些结构复杂的对象的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但他们却拥有比较稳定的一致的接口
如何应对变化?如何向客户端隔离出这些易变的对象,从而使得依赖这些易变对象的客户程序不会随着需求的变化而变化?
UML类图
代码实现
import java.io.*;
public abstract class Prototype implements Serializable,Cloneable {
public Prototype deepClone() throws IOException, ClassNotFoundException {
//将对象写入流中,
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bao);
oos.writeObject(this);
//将对象取出来
ByteArrayInputStream bi = new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bi);
return (Prototype)ois.readObject();
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ConcretePrototype concretePrototype = new ConcretePrototype();
Prototype prototype = concretePrototype.deepClone();
System.out.println(concretePrototype);
System.out.println(prototype);
System.out.println(concretePrototype.getClass().getName());
System.out.println(prototype.getClass().getName());
}
}
class ConcretePrototype extends Prototype{
}
2.单例模式
动机
在软件系统种,经常存在着某些特殊的类,必须保证他们在系统中只有一个实例,才能确保逻辑的正确性或良好的效率
如何绕过常规的构造器,提供一个机制来保证一个类只有一个实例?这是设计者的责任,而不是客户端程序员的责任
UML类图
代码实现
(1)饿汉式
//饿汉模式:线程安全,耗费资源。
public class HugerSingletonTest {
//该对象的引用不可修改
private static final HugerSingletonTest ourInstance = new HugerSingletonTest();
public static HugerSingletonTest getInstance() {
return ourInstance;
}
private HugerSingletonTest() {}
}
(2)懒汉式
public class Singleton {
private static Singleton ourInstance;
public static Singleton getInstance() {
if (null == ourInstance) {
synchronized (Singleton.class) {
if (null == ourInstance) {
ourInstance = new Singleton();
}
}
}
return ourInstance;
}
private Singleton() {}
}
(3)静态内部类
public class Singleton {
private static class SingletonHodler {
private static final Singleton ourInstance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHodler.ourInstance;
}
private Singleton() {}
}
(4)枚举
enum SingletonTest {
INSTANCE;
public void whateverMethod() {
}
}
开发实例
package com.utils;
/**
* Created by xsl on 2020/7/31 10:57
*/
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
/**
* @ClassName ThreadPool
* @Description: 线程池 单例与代理模式
* @Author xsl
* @Date 2020/7/31 10:57
**/
public class ThreadPool {
/**
* 初始化核心线程数
*/
private static final int processors = Runtime.getRuntime().availableProcessors();
/**
* 线程池最大容量
*/
private static int maxPoolSize = processors * 2;
/**
* 扩容线程数闲置寿命
*/
private static int keepAliveTime = 2;
/**
* 等待队列长度
*/
private static int waitQueueSize = 1000;
/**
* 拒绝策略
*/
private static RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
/**
* 线程池实例,懒汉式
*/
private static ThreadPool instance = null;
/**
* 可重用锁
*/
private static ReentrantLock lock = new ReentrantLock();
/**
* 线程池
*/
private static ExecutorService fixedThreadPool = null;
private ThreadPool() {
//私有构造器
}
public ExecutorService getExecutorService() {
return fixedThreadPool;
}
public static ThreadPool getInstance() {
//双重判断加锁
if (instance == null) {
lock.lock();
if (instance == null) {
instance = new ThreadPool();
//使用ThreadPoolExecutor不要使用Executors
fixedThreadPool = new ThreadPoolExecutor(
processors,
maxPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(waitQueueSize),
Executors.defaultThreadFactory(),
handler
);
}
lock.unlock();
}
return instance;
}
}
3.工厂方法
动机
在软件系统中,经常面临着创建的对象(或绑定的对象)发生需求的变化,所以期望统一套代码通过动态绑定的形式来抵抗这样的变化
UML类图
代码实现
interface Factory{
Product createProduct();
}
interface Product{
}
class ConcreteProduct1 implements Product{
}
class ConcreteFactory1 implements Factory{
@Override
public Product createProduct() {
return new ConcreteProduct1();
}
}
4.抽象工厂
动机
在抽象工厂是工厂方法的一个扩展,当我们要创建的对象不止一个,且这些对象还是成套出现的时候,我们就必须要使用某种方式对这样的成套就行约束
UML类图
代码实现
interface Factory{
Product1 createProduct1();
Product2 createProduct2();
}
interface Product1{
}
interface Product2{
}
class ConcreteProduct1 implements Product1{
}
class ConcreteProduct2 implements Product2{
}
class ConcreteFactory1 implements Factory{
@Override
public Product1 createProduct1() {
return new ConcreteProduct1();
}
@Override
public Product2 createProduct2() {
return new ConcreteProduct2();
}
}
5.建造者模式
动机
在软件系统中,有时候面临着一个复杂对象的创建工作,其通常用各个部分的子对象用一定算法构成,由于需求的变化,这个复杂对象的内部经常面临着剧烈的变化,但将他们组合在一起的算法却相对稳定的时候适合使用建造者模式
UML类图
代码实现
class Product{
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
}
abstract class Builder{
protected Product product = new Product();
public abstract void createPartA();
public abstract void createPartB();
public abstract void createPartC();
public Product getProduct(){
return product;
}
}
class ConcreteBuilder extends Builder{
@Override
public void createPartA() {
product.setPartA("A");
}
@Override
public void createPartB() {
product.setPartA("A");
}
@Override
public void createPartC() {
product.setPartA("A");
}
}
class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product createProduct(){
builder.createPartA();
builder.createPartB();
builder.createPartC();
return builder.getProduct();
}
}
二、结构型模式
1.代理模式
动机
对象增强、权限隔离,方法改写等,代理模式的用途很广泛
UML类图
代码实现
(1)静态代理
interface Subject{
public void request();
}
class RealSubject implements Subject{
@Override
public void request() {
System.out.println("aaa");
}
}
class Proxy implements Subject{
private RealSubject realSubject = new RealSubject();
@Override
public void request() {
//某些操作或直接改写某些方法
realSubject.request();
//某些操作
}
}
(2)jdk动态代理
public class A {
public static void main(String[] args) {
ProxyObject proxy = new ProxyObject(new RealSubject());
Subject subject = (Subject)Proxy.newProxyInstance(
RealSubject.class.getClassLoader(),
RealSubject.class.getInterfaces(),
proxy
);
subject.request();
}
}
interface Subject{
public void request();
}
class RealSubject implements Subject{
@Override
public void request() {
System.out.println("aaa");
}
}
class ProxyObject implements InvocationHandler {
private Object target;
public ProxyObject(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("aaa");
Object retVal = method.invoke(target, args);
return retVal;
}
}
(3)Cglib动态代理
cglib动态代理需要引入依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
public class A{
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Subject.class);
enhancer.setCallback(new LogInterceptor());
Subject subject = (Subject)enhancer.create();
subject.request();
}
}
class Subject{
public void request(){
System.out.println("aaa");
}
}
class LogInterceptor implements MethodInterceptor {
/**
*
* @param obj 表示要进行增强的对象
* @param method 表示拦截的方法
* @param objects 数组表示参数列表,基本数据类型需要传入其包装类型,如int-->Integer、long-Long、double-->Double
* @param methodProxy 表示对方法的代理,invokeSuper方法表示对被代理对象方法的调用
* @return 执行结果
* @throws Throwable 异常
*/
@Override
public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before(method.getName());
// 注意这里是调用invokeSuper而不是invoke,否则死循环;
// methodProxy.invokeSuper执行的是原始类的方法;
// method.invoke执行的是子类的方法;
Object result = methodProxy.invokeSuper(obj, objects);
after(method.getName());
return result;
}
/**
* 调用invoke方法之前执行
*/
private void before(String methodName) {
System.out.println("调用方法" + methodName +"之【前】的日志处理");
}
/**
* 调用invoke方法之后执行
*/
private void after(String methodName) {
System.out.println("调用方法" + methodName +"之【后】的日志处理");
}
}
(3)jassist动态代理
这个更牛,简直无所不能,怎么实现代理模式自行百度吧,这里展示它的强大之处
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.20.0-GA</version>
</dependency>
public static void main(String[] args) throws CannotCompileException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NotFoundException {
// 创建类
ClassPool pool = ClassPool.getDefault();
CtClass cls = pool.makeClass("cn.ibm.com.TestClass");
// 添加私有成员name及其getter、setter方法
CtField param = new CtField(pool.get("java.lang.String"), "name", cls);
param.setModifiers(Modifier.PRIVATE);
cls.addMethod(CtNewMethod.setter("setName", param));
cls.addMethod(CtNewMethod.getter("getName", param));
cls.addField(param, CtField.Initializer.constant(""));
// 添加无参的构造体
CtConstructor cons = new CtConstructor(new CtClass[] {}, cls);
cons.setBody("{name = \"Brant\";}");
cls.addConstructor(cons);
// 添加有参的构造体
cons = new CtConstructor(new CtClass[] {pool.get("java.lang.String")}, cls);
cons.setBody("{$0.name = $1;}");
cls.addConstructor(cons);
// 打印创建类的类名
System.out.println(cls.toClass());
// 通过反射创建无参的实例,并调用getName方法
Object o = Class.forName("cn.ibm.com.TestClass").newInstance();
Method getter = o.getClass().getMethod("getName");
System.out.println(getter.invoke(o));
// 调用其setName方法
Method setter = o.getClass().getMethod("setName", new Class[] {String.class});
setter.invoke(o, "Adam");
System.out.println(getter.invoke(o));
// 通过反射创建有参的实例,并调用getName方法
o = Class.forName("cn.ibm.com.TestClass").getConstructor(String.class).newInstance("Liu Jian");
getter = o.getClass().getMethod("getName");
System.out.println(getter.invoke(o));
}
2.适配器模式
动机
将一个现有对象放在新环境中使用,但是现有对象并不能完全满足该新环境场景
UML类图
代码实现
public class A {
public static void main(String[] args) {
TargetAdapter targetAdapter = new TargetAdapter(new Adapter());
targetAdapter.request();
}
}
interface Target{
void request();
}
class Adapter{
void specificRequest() {
System.out.println("适配者中的业务代码被调用!");
}
}
class TargetAdapter implements Target{
private Adapter adapter;
public TargetAdapter(Adapter adapter) {
this.adapter = adapter;
}
@Override
public void request() {
adapter.specificRequest();
}
}
3.桥接模式
动机
某个类型有多个维度的变化,如何应对这种多个维度的变化,使用面向对象的技术使得类型可以沿着多个方向发生变化
UML类图
代码实现
public class A {
public static void main(String[] args) {
HuaWei huaWei = new HuaWei(new OnlineSale());
huaWei.make();
}
}
abstract class Computer{
protected Sale sale;
public Computer(Sale sale) {
this.sale = sale;
}
abstract void make();
}
class HuaWei extends Computer{
public HuaWei(Sale sale) {
super(sale);
}
@Override
void make() {
System.out.println("制造华为");
sale.sale();
}
}
interface Sale{
void sale();
}
class OnlineSale implements Sale{
@Override
public void sale() {
System.out.println("线上销售");
}
}
class Offline implements Sale{
@Override
public void sale() {
System.out.println("线下销售");
}
}
4.装饰器模式
动机
在某些情况下我们会过度使用继承来扩展对象的功能,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多,各种子类的组合会导致子类的膨胀
如何使对象功能的扩展能根据需要的动态来实现?同时避免扩展功能的增多带来的子类膨胀问题?从而使得任何功能扩展变化所导致的影响最低?
UML类图
代码实现
public class DecoratorPattern {
interface Stream{
/**
* 读
*/
void read();
/**
* 写
*/
void write();
}
class FileStream implements Stream{
@Override
public void read() {
//实现
}
@Override
public void write() {
//实现
}
}
/**
* 装饰器
*/
class BufferStream implements Stream{
Stream stream;
public BufferStream(Stream stream) {
this.stream = stream;
}
@Override
public void read() {
//缓冲处理
stream.read();
}
@Override
public void write() {
//缓冲处理
stream.write();
}
}
}
5.外观模式
动机
外观模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
UML类图
代码实现
public class A {
public static void main(String[] args) {
Facade facade = new Facade();
facade.method();
}
}
class Facade{
private System1 system1 = new System1();
private System2 system2 = new System2();
private System3 system3 = new System3();
public void method(){
system1.operation();
system2.operation();
system3.operation();
}
}
class System1{
public void operation(){
System.out.println("System1");
}
}
class System2{
public void operation(){
System.out.println("System2");
}
}
class System3{
public void operation(){
System.out.println("System3");
}
}
6.享元模式
动机
在软件系统中采用纯粹对象的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价
某些对象本来可以被重复利用,可能频繁的创建和销毁会对系统有性能损耗
UML类图
代码实现
public class FlyweightPattern {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
Flyweight f01 = factory.getFlyweight("a");
Flyweight f02 = factory.getFlyweight("a");
Flyweight f03 = factory.getFlyweight("a");
Flyweight f11 = factory.getFlyweight("b");
Flyweight f12 = factory.getFlyweight("b");
f01.operation(new UnsharedConcreteFlyweight("第1次调用a。"));
f02.operation(new UnsharedConcreteFlyweight("第2次调用a。"));
f03.operation(new UnsharedConcreteFlyweight("第3次调用a。"));
f11.operation(new UnsharedConcreteFlyweight("第1次调用b。"));
f12.operation(new UnsharedConcreteFlyweight("第2次调用b。"));
}
}
//非享元角色
class UnsharedConcreteFlyweight {
private String info;
UnsharedConcreteFlyweight(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
//抽象享元角色
interface Flyweight {
public void operation(UnsharedConcreteFlyweight state);
}
//具体享元角色
class ConcreteFlyweight implements Flyweight {
private String key;
ConcreteFlyweight(String key) {
this.key = key;
System.out.println("具体享元" + key + "被创建!");
}
public void operation(UnsharedConcreteFlyweight outState) {
System.out.print("具体享元" + key + "被调用,");
System.out.println("非享元信息是:" + outState.getInfo());
}
}
//享元工厂角色
class FlyweightFactory {
private HashMap<String, Flyweight> flyweights = new HashMap<String, Flyweight>();
public Flyweight getFlyweight(String key) {
Flyweight flyweight = (Flyweight) flyweights.get(key);
if (flyweight != null) {
System.out.println("具体享元" + key + "已经存在,被成功获取!");
} else {
flyweight = new ConcreteFlyweight(key);
flyweights.put(key, flyweight);
}
return flyweight;
}
}