设计模式
策略模式
定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换
环境类:操作策略的上下文环境,eg游客
抽象策略类:策略的抽象,eg出行方式的抽象
具体策略类:具体策略的实现,eg出行的具体实现
//抽象策略接口
interface TravelStrategy{
public function travelAlgorithm();
}
//具体策略类
public class TrainStrategy implements TravelStrategy{
@Override
public void travelStyle(){
System.out.println("TAKE THE TRAIN...");
}
}
public class HighTrainStrategy implements TravelStrategy{
@Override
public void travelStyle(){
System.out.println("TAKE THE HIGHTRAIN...");
}
}
public class AirStrategy implements TravelStrategy{
@Override
public void travelStyle(){
System.out.println("TAKE THE AIRPLANE...");
}
}
//环境类
public class Traveler{
TravelStrategy travelStrategy;
//设置出行策略
public void setTravelStrategy(TravelStrategy travelStrategy){
this.travelStrategy = travelStrategy;
}
//为当前用户设置出行方式
public void travelStyle(){
travelStrateg.travelStyle();
}
public static void main(String[] args){
Traveler traveler = new Traveler();
traveler.setTravelStrategy(new TrainStrategy());
traveler.travelStyle();
}
}
策略模式的优点:
我们之前在选择出行方式的时候,往往会使用if-else语句,也就是用户不选择A那么就选择B这样的一种情况。这种情况耦合性太高了,而且代码臃肿,有了策略模式我们就可以避免这种现象,策略模式遵循开闭原则,实现代码的解耦合。扩展新的方法时也比较方便,只需要继承策略接口就好了
缺点:
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。策略模式会出现很多的策略类。context在使用这些策略类的时候,这些策略类由于继承了策略接口,所以有些数据可能用不到,但是依然初始化了。
策略模式 VS 工厂模式
工厂模式是创建型模式 ,它关注对象创建,提供创建对象的接口,让对象的创建与具体的使用客户无关。 策略模式是对象行为型模式 ,它关注行为和算法的封装 。再举个例子,还是我们出去旅游,对于策略模式我们只需要选择其中一种出行方法就好,但是工厂模式不同,工厂模式是你决定哪种旅行方案后,由工厂代替你去构建具体方案(工厂代替你去买火车票)。
代理模式
提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.代理对象是对目标对象的扩展,并会调用目标对象
静态代理
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.
//接口
public interface IUserDao{
void save();
}
//目标对象
public class UserDao implements IUserDao{
public void save(){
System.out.println("-----SAVE DATA!-----");
}
}
//代理对象
public class UserDaoProxy implements IUserDao{
private IUserDao target;
public UserDaoProxy(IUserDao target){
this.target = target;
}
public void save(){
System.out.println("Start...");
target.save();//执行目标对象的方法
System.out.println("Commit...");
}
}
//测试类
public class App{
public static void main(String[] args){
UserDao target = new UserDao();//目标对象
UserDaoProxy proxy = new UserDaoProxy(target);//建立代理关系
proxy.save();//执行代理方法
}
}
总结:
1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.缺点:
- 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
动态代理
代理对象不需要实现接口,动态代理AKA接口代理,JDK代理
动态代理解决的问题是面对新的需求时,不需要修改代理对象的代码,只需要新增接口和真实对象,在客户端调用即可完成新的代理。
目的:满足软件工程的开闭原则,提高类的可维护性和可扩展性。
JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是:
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
classLoader当前目标对象使用类加载器,interface目标对象实现的接口的类型,InvocationHandler事件处理,执
行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
//接口
public interface IUserDao{
void save();
}
//目标对象
public class UserDao implements IUserDao{
public void save(){
System.out.println("-----SAVE DATA!-----");
}
}
//动态代理对象:代理工厂类
public class ProxyFactory{
//保存接收目标对象
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
//给目标对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyIntsance(target.getClass().getClassLoader(),
target.getClass().getInterface(),
new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
System.out.println("START2...");
Object returnValue = methos.invoke(target, args);
System.out.println("COMMIT2...");
return returnValue;
} });
}
}
//测试类
public class App{
public static void main(String[] args){
//目标对象
IUserDao target = new UserDao();
System.out.println(target.getClass());
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
System.out.printl(proxy.getClass());
proxy.save();
}
}
总结:
代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
Cglib代理
有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理
Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
CGLIB可以代理没有实现接口的Java类
//目标对象
public class UserDao{
public void save(){
System.out.println("-----SAVE DATA!-----");
}
}
//Cglib代理工厂
public class ProxyFactory implements MethodInterceptor{
//维护目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("开始事务...");
//执行目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务...");
return returnValue;
}
}
//测试类
public class App {
public void test(){
//目标对象
UserDao target = new UserDao();
//代理对象
UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法
proxy.save();
}
}
总结:必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,因为采用的是继承,所以该类或方法最好不要生成final,对于final类或方法,是无法继承的

浙公网安备 33010602011771号