设计模式学习
策略模式
工厂模式:
简单工厂:
一个工厂创建所有实例
工厂方法:
父类定义工厂方法 子类实现具体的实现
抽象工厂:
定义一个工厂的接口,所有的具体工厂实现接口
装饰者模式:
- 装饰者模式需要定义共同的定义行为的接口;
- 指的是在装饰者在被装饰着上面增加行为接口;
- 不改变具体代理 动态叠加增强行为功能
- 装饰着比继承提供了更为灵活的替代方案
- 装饰者持有一个被装饰着的对象。
- 继承装饰者类,并实现扩展功能
代理模式:
相对于装饰者模式而言,代理模式意味者在使用者控制使用者对目标对象的访问,以及增强功能。
静态代理:
在运行前已经生成了class类
动态代理:
在代理运行过程中,由于反射机制动态创建而成
JDK的动态代理
Java.lang.reflect.Proxy.newProxyInstance()类创建代理对象,
参数说明:类加载器ClassLoader,提供代理实现的接口,增强的Handler对象:需要实现java.lang.reflect.InvocationHandler接口;
Java.lang.reflect.invocationHandler().invoke() 提供增强功能z
被代理的对象
public class TeacherChen implements Boy {
public boolean dating(char cup) { }
public void show() {//dosomething}
}
代理类的实现
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Subject {
void request();
}
class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
class MyInvocationHandler implements InvocationHandler {
private Object realSubject;
public MyInvocationHandler(Object realSubject) {
this.realSubject = realSubject;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method invocation.");
Object result = method.invoke(realSubject, args);
System.out.println("After method invocation.");
return result;
}
}
public class Example {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new MyInvocationHandler(realSubject);
Subject proxySubject = (Subject) Proxy.newProxyInstance(
Subject.class.getClassLoader(),
new Class<?>[]{Subject.class},
handler
);
proxySubject.request();
}
}
测试代码
public class PlayGame {
public static void main(String[] args) {
System.out.println("JDK动态代理:");
Boy tcc = new TeacherChen();
Boy tony2 = (Boy) TonyCompany.proxy(tcc);
tony2.dating('E');
tony2.show();
ProxyUtils.generateClassFile(Boy.class, tony2.getClass().getName());
}
}
CGLIB的代理模式
创建代理对象
Enhancer.create():Obj
Enhancer.createClass():CLass
代码增强
Interface Callback
——>interface MethodInterceptor.intercept()
并持有被增强对象target:Obj
回调增强,对不同的方法实现不同的增强
Interface CallbackFilter.accept(method):int
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
class RealSubject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
class MyMethodInterceptor implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method invocation.");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method invocation.");
return result;
}
}
public class Example {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new MyMethodInterceptor());
RealSubject proxySubject = (RealSubject) enhancer.create();
proxySubject.request();
}
}
责任链模式
抽象一个责任接口
Responsibility.process(request,chian)
public class ResponsibilityChain {
private List<Responsibility> responsibilitys;
private int index = 0;
public ResponsibilityChain() { this.responsibilitys = new ArrayList<>(); }
public void process(Request request) {
if (this.index < this.responsibilitys.size()) {
this.responsibilitys.get(index++).process(request, this);
}
}
public void register(Responsibility res) {
this.responsibilitys.add(res);
}
}
和装饰模式区别
装饰模式需要持有一个被装饰的对象,责任链将所有的责任链交给责任接口
适配器模式
使用者和提供者的接口不一致,增加一层适配者
外观模式
提供一个新的接口影藏复杂的调用过程影藏
观察者模式
一个被观察的主题接口 一个观察者接口
<interface> Observer.update(obj)
<interface>Subject.addObserver(observer)
.removeObserver(observer)
.notifyObservers();
Java.util.Observable 可被观察的主题,具体的主题扩展他
Java.util.Observer 观察者接口,具体观察者 实现这个接口
public static void main(String[] args) {
Observable subject1 = new Observable() {
public synchronized void notifyObservers(Object data) {
this.setChanged();
super.notifyObservers(data);
}
};
subject1.addObserver(new Observer() {
@Override
public void update(Observable o, Object arg) {
System.out.println("观察者1收到通知被更新了..." + arg);
}
});
new Thread(()->{
subject1.addObserver((o,arg)->{
System.out.println(o.toString());
System.out.println(arg.toString());
System.out.println("观察者2收到通知被更新了..." + arg);
});
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
subject1.notifyObservers("change1");
subject1.notifyObservers("change2");
}
命令模式
场景:命令行界面,用户可以输入命令执行某项功能;系统的功能在逐步增加,命令也在增加,
命令行程序
Receiver.commends:Map
.register(String,Commend)
.receive(String)
<interface>Commend.execute()
命令模式和策略模式的区别
策略模式侧重的是一个行为的多个算法实现,可以互换算法
命令模式侧重的是位多个行为提供灵活的执行方式
状态模式:
场景:一个类对外提供了多个状态,同时具有多个行为,不同的状态下的对外的行为不同。
<interface> State:pay()
refund()
buy()
getCoffee()
对应每一个状态实现一个状态对象,不同的状态有不同的实例
桥接模式
在两个维度上比如形状和颜色维度进行设计模式
<abstract> Shape.color:Color
.draw()
单例模式
饥汉模式:
持有一个静态块对象或者静态属性的对象,使用公开的方法返回这个对象
懒汉模式:
错误示范:
public class Singleton {
private static Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
public class Singleton {
private static Singleton singleton;
private Singleton(){}
public static synchronized Singleton getInstance(){
if (singleton == null){
synchronized (Singleton.class) {
singleton = new Singleton();
}
}
return singleton;
}
}
正确方式(线程安全 但是性能有问题)
public class Singleton {
private static Singleton singleton;
private Singleton(){}
public static synchronized Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
// 没有线程安全
public class Singleton {
//对象的可见性,在一个线程对对象做了更新后,其他对象3很有可能访问不到最新的对象
//不能保证并发的线程不能看到线程变化的最新值
private static volatile Singleton singleton;
private Singleton(){}
public static synchronized Singleton getInstance(){
if (singleton == null){
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
//静态内部类:使用类加载机制
//类的静态属性只能在类加载的过程中一次加载,在类在加载的时候别的线程是无法进去的
public class Singleton {
private Singleton(){}
private static class SingletonInstance{
private static final Singleton SINGLETON = new Singleton();
}
public static Singleton getInstance(){
return SingletonInstance.SINGLETON;
}
}
使用枚举的方式
public enum Singleton {
SINGLETON;
public void whateverMethod(){}
}
模板方法模式
场景:当设计一个类,能明确他对外界提供的某个方法的内部执行步骤,但是有的步骤不同的类有有不同的行为。
public abstract class Game {
protected abstract void init();
protected abstract void start();
protected abstract void end();
public final void play(){
init();
start();
end();
}
}