一些思考
如果刚上手直接就看设计模式的话,大概只是知道有那些东西,记得观察者,单例,工厂这些单词(至少我是这样)。设计模式那么多种,有些未必常用,很难记得那么多,准备只是理解一下现在接触的这些设计模式,其他的不再刻意去了解。
从我自己觉得简单的说起;
单例模式(Singleton)
很多时候,我们会遇到某些类的对象只能有一个实例,比如线程池、缓存等。
以下是实现一个简单单例模式的一个代码示例:
public class Singleton {
private static Singleton instance=null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
过程:
一、利用一个静态变量记录Singleton类的唯一实例;
二、把构造器声明为私有,只有在Singleton类内部才可以调用;
三、用getInstance()方法实例化对象并且返回实例;
要点:
一、相对于设置为全局变量的优点在于,单例模式不需要在程序的一开始声明,只需要在需要的时候创建;
二、单例模式需考虑多线程问题,进行进一步优化;
三、如果使用多个类加载器,有可能使得单例失效出现多个实例,这时候需要指定类加载器。
代理模式(Proxy)
应用场景:
代理模式在访问实际对象时引入一定程度的间接性,这种间接性可以附加多种用途。这里的间接性是指不直接调用实际对象的方法,那么我们在代理过程中就可以加上一些其他用途,这样降低系统的耦合度。
静态代理:
抽象角色
public interface IUserDao {
void save();
}
真实角色
public class UserDao implements IUserDao {
public void save() {
System.out.println("----已经保存数据!----");
}
}
代理角色
public class UserDaoProxy implements IUserDao{
//接收保存目标对象
private IUserDao target;
public UserDaoProxy(IUserDao target){
this.target=target;
}
public void save() {
System.out.println("开始事务...");
target.save();//执行目标对象的方法
System.out.println("提交事务...");
}
}
测试类:
public class App {
public static void main(String[] args) {
//目标对象
UserDao target = new UserDao();
//代理对象,把目标对象传给代理对象,建立代理关系
UserDaoProxy proxy = new UserDaoProxy(target);
proxy.save();//执行的是代理的方法
}
}
动态代理:
代理类所在包:java.lang.reflect.Proxy;
JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数。
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
ClassLoader loader用来指明生成代理对象使用哪个类装载器,Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler h用来指明产生的这个代理对象要做什么事情。所以我们只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了
参考链接
https://www.cnblogs.com/cenyu/p/6289209.html
工厂模式(Factory)
简单工厂:
又被称为静态工厂方法(Static Factory Method)模式,简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
观察者模式(Observer)
观察者模式主要是用于建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。
观察者模式的四个组件:
- 抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
-
public class Subject { private List<Observer> list = new ArrayList<Observer>(); public void registerObserver(Observer obs){ list.add(obs); } public void removeObserver(Observer obs){ list.remove(obs); } //通知所有的观察者更新状态 public void notifyAllObserver(){ for(Observer obs : list){ obs.update(this); } } }
- 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
public interface Observer {
void update(Subject subject);
}
- 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
public class ConcreteSubject extends Subject {
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
this.notifyAllObserver();
}
}
- 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与主体的状态相协调。
public class ObserverA implements Observer{
private int myState;
@Override
public void update(Subject subject) {
myState = ((ConcreteSubject)subject).getState();
}
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
}
装饰器模式(Decorator)
应用场景:
如果需要为一个已经定义好的类添加新的职责(操作),通常会定义一个新类继承自定义好的类,但是通过继承的方式解决这样的问题还带来了系统的复杂性,因为继承的深度会变得很深。而装饰器提供了一种给类增加职责的方法,不是通过继承实现的,而是通过组合。
简单介绍:
装饰器的价值在于装饰,他并不影响被装饰类本身的核心功能。在一个继承的体系中,子类通常是互斥的。比如一辆车,品牌只能要么是奥迪、要么是宝马,不可能同时属于奥迪和宝马,而品牌也是一辆车本身的重要属性特征。但当你想要给汽车喷漆,换坐垫,或者更换音响时,这些功能是互相可能兼容的,并且他们的存在不会影响车的核心属性:那就是他是一辆什么车。这时你就可以定义一个装饰器:喷了漆的车。不管他装饰的车是宝马还是奥迪,他的喷漆效果都可以实现。
装饰器模式的四个组件:
抽象组件(Component):需要装饰的抽象对象。
具体组件(ConcreteComponent):是我们需要装饰的对象
抽象装饰类(Decorator):内含指向抽象组件的引用及装饰者共有的方法。
具体装饰类(ConcreteDecorator):被装饰的对象。