做网站需要跟客户了解什么软件,招商网址,莱州网监局,如何做企业网站建设java设计模式java设计模式类型常用设计模式单例模式单例模式的两种创建方式饿汉式单例懒汉式单例工厂模式简单工厂模式工厂方法模式抽象工厂模式原型模式代理模式代理模式结构静态代理动态代理jdk代理Cglib代理java设计模式类型
根据完成的工作类型设计模式分为创建型模式、结…
java设计模式java设计模式类型常用设计模式单例模式单例模式的两种创建方式饿汉式单例懒汉式单例工厂模式简单工厂模式工厂方法模式抽象工厂模式原型模式代理模式代理模式结构静态代理动态代理jdk代理Cglib代理java设计模式类型
根据完成的工作类型设计模式分为创建型模式、结构型模式和行为型模式。
创建型模式:是用来创建对象的模式特点是将对象的创建和使用分离。有单例、原型、工厂方法、抽象工厂、建造者5中创建型模型
结构型创建模式是用来将类或对象按某种布局组成更大的结构有代理、桥接、组合等7种结构性模式
行为型模式是用来将类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务以及怎样分配职责。。提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器 11 种行为型模式。
常用设计模式
单例模式
为了节省资源、保证数据内容的一致性某些类只能创建一个实例这就是单例模式
单例模式的特点只有一个实例对象、该单例对象必须由单例类创建、单例类提供一个访问方法可以让外部类进行获取。
单例模式的两种创建方式
饿汉式单例
类一旦加载就会创建一个实例不会存在线程安全问题
private static Demo demonew Demo();private Demo(){}public Demo getInstance(){return demo;}懒汉式单例
类加载时没有创建单例对象只有第一次调用getInstance方法时才会去创建这个单例
private static Demo demo;private Demo(){}public Demo getInstance(){if(demonull){demonew Demo();}return demo;}这种方式存在线程安全问题当多个线程同时访问时会出现创建多个对象的情况。
优化
//这种方式虽然安全但是效率低
public synchronized Demo getInstance(){if(demonull){demonew Demo();}return demo;}
//这种方式是线程安全的效率也高但是在执行过程中可能会出现代码重排序的问题
public Demo getInstance(){//这里使用双重判断第一个判断语句是为了判断当线程进来时是demo是否被创建。if(demonull){synchronized (Demo.class){//这个判断语句主要是判断对象未创建时第一次进来的请求进入时的判断。if(demonull){demonew Demo(); } } }return demo;}//最终优化 使用volatile和双重检索
private static volatile Demo demo;public Demo getInstance(){if(demonull){synchronized (Demo.class){if(demonull){demonew Demo();}}}return demo;}Jdk 中的源码 Runtime 类就是一个单例类利用 Runtime 类可以启动新的进程或进行相关运行时环境的操作。比如取得内存空间以及释放垃圾空间。
工厂模式
工厂负责批量创建对象使用对象时只需要找到相对应的工厂
简单工厂模式
不符合开闭原则适合长聘子类少的、创建操作简单的情况 该模式包含的角色:
工厂角色负责创建所有实例的内部逻辑提供静态方法可以被外界调用创建产品对象。
抽象产品角色是所有对象的父类可以时接口或抽象类
具体产品角色是简单工厂模式的创建目标。
优点实现的对象创建和调用的分离。
缺点违背了开闭原则产品子类过多会导致工厂类非常庞大违背了高内聚原则‘
//汽车类 抽象产品角色
public interface Car {void run();}
//奥迪类 具体产品角色
public class Aodi implements Car{Overridepublic void run() {System.out.println(奥迪汽车行驶);}
}
//宝马类 具体产品角色
public class Bmw implements Car{Overridepublic void run() {System.out.println(宝马汽车行驶);}}
// 汽车工厂 工厂角色
public class CarFactory {public static Car createCar(String name){if(name.equals(aodi)){Aodi aodi new Aodi();//aodi.return aodi;}if(name.equals(bmw)){return new Bmw();}return null;}
}工厂方法模式
在简单工厂模式的基础上对工厂也进行了抽象解决了违背开闭原则的问题 该模式中包含的角色及其职责.
抽象工厂角色工厂方法模式的核心与应用程序无关。任何在模式中创建的对 象的工厂类必须实现这个接口。 具体工厂角色这是实现抽象工厂接口的具体工厂类包含与应用程序密切相关 的逻辑并且受到应用程序调用以创建产品对象。 抽象产品角色工厂方法模式所创建的对象的父类型也就是产品对象的共同父 类或共同拥有的接口。 具体产品角色这个角色实现了抽象产品角色所定义的接口。某具体产品有专门 的具体工厂创建它们之间往往——对应。
//抽象工厂类
public interface CarFactory {Car createCar();}
//具体工厂角色
public class AodiFactory implements CarFactory{Overridepublic Car createCar() {return new AodiCar();}
}
public class BCFactroy implements CarFactory{Overridepublic Car createCar() {return new BC();}}
//抽象产品角色
public interface Car {void run();
}
//具体产品角色
public class AodiCar implements Car{Overridepublic void run() {System.out.println(奥迪汽车行驶);}
}
public class BC implements Car{Overridepublic void run() {System.out.println(奔驰);}
}
抽象工厂模式
抽象工厂模式中一个具体的工厂负责创建一系列相互关联的产品。
//抽象工厂类
public interface AbstractFactory {Car getCar();Phone getPhone();}
//具体工厂角色
public class AodiFactory implements AbstractFactory{Overridepublic Car getCar() {return new AodiCar();}Overridepublic Phone getPhone() {return new AodiPhone();}
}
//抽象产品角色
public interface Phone {void call();
}
public interface Car {void run();
}
//具体产品角色
public class AodiCar implements Car{Overridepublic void run() {System.out.println(奥迪汽车行驶);}
}
public class AodiPhone implements Phone{Overridepublic void call() {System.out.println(奥迪手机打电话);}
}优点获取具体系列产品只需要通过具体系列工厂获取无序关心创建的细节。
原型模式
原型模式是指创建一个对象并且通过这个对象作为原型来创建新的对象相当于复制多个具有相同信息的对象。
实现方式使用对象克隆的方式创建新的对象。
代理模式
代理模式就是给对象提供一个代理通过代理对象来对原对象进行控制。是的客户不能直接和对象进行交互只能通过代理对象来进行操作。
案例买火车票不一定要去火车站买可以通过 12306 网站或者去火车票代售点
优点保护目标对象、代理对象可以扩展目标对象的功能代理模式将客户端与目标分离降低系统的耦合度。
代理模式结构
1.抽象主题类使用接口和抽象类声明真实主题类和代理对象的业务方法
2.真实主题类实现抽象主题中的业务是目标对象是最终要引用的对象。
3.代理类提供与真实主题相同的结构引用了真实主题它可以访问、控制和扩展真实主题的功能 1.png)]
代理分为两种动态代理和静态代理
静态代理
静态代理的特点。代理类接受一个抽象主题接口实现任何该接口的对象都可以通过代理类进行代理。
优点可以对目标对象进行功能扩展
缺点一个代理类只能代理一个接口必须现有接口再有代理接口发生改变代理类也要修改
以买票为例
//抽象主题 买票
public interface Ticket {void buy();
}
//真实主题 目标对象类
public class TrainTicket implements Ticket {Overridepublic void buy() {System.out.println(买火车票);}
}
public class PlaneTicket implements Ticket {Overridepublic void buy() {System.out.println(买飞机票);}
}
//代理类
public class MeiTuan implements Point {Ticket ticket;public MeiTuan(Ticket ticket) {this.ticket ticket;}Overridepublic void buy() {System.out.println(添加额外功能);ticket.buy();}
}
//测试类
public class Test {public static void main(String[] args) {//具体对象Ticket trainTicket new TrainTicket();Ticket planeTicket new PlaneTicket();//创建用户代理对象Ticket ticket new Ticket(trainTicket);ticket.buy();Ticket ticket1 new Ticket(planeTicket);ticket1.buy();}
}动态代理
在动态代理中不需要手动的创建类只需要编写一个动态的处理器代理对象在运行时动态的来创建。
动态代理分为jdk动态代理和cglid动态代理
jdk代理
jdk动态代理是通过反射来实现的借助java自带的java.lang.reflect.Proxy生成。
实现步骤
1.编写一个委托类的接口
2.实现一个委托类
3.创建一个动态代理类实现现 InvocationHandler 接口并重写该 invoke 方法。
4.在测试类中生成动态代理的对象。
实现步骤的前两步和静态代理没有区别。
/*动态代理类代理类不需要实现与目标类相同的接口,这样就可以代理任意的目标类但是是有要求的,目标类必需实现接口,此种方式是动态代理的实现方式之一: jdk代理 是一种纯反射机制实现(动态获取目标类接口方法)*/
public class DynamicProxy implements InvocationHandler {Object object;//真实对象,接收任何的目标类对象public DynamicProxy(Object object) {this.object object;}/*在代理类中调用目标类中的具体方法,动态的将代理动态对象,目标类中要调用的方法,及方法中的参数传递过来Method method 就是动态获取的真正要执行的方法*/Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(之前开启事务);method.invoke(object);System.out.println(之后提交事务);return proxy;}//真正意义上,运行时生成代理对象的方法public Object getProxy(){return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);}}
//测试类
public class Test {public static void main(String[] args) {TrainTicket trainTicket new TrainTicket();DynamicProxy dtproxy new DynamicProxy(trainTicket);//自己创建的代理类对象//这才是真正的创建动态代理对象Ticket ticket (Train)dtproxy.getProxy();userDao.saveUser();//使用代理对象调用接口中的方法,获取当前调用的方法,最终调用invoke方法}
}
jdk动态代理减少了对接口业务的依赖降低了耦合度但是jdk动态代理有一个缺点就是他必须要创建一个代理接口。
Cglib代理
Cglib代理解决了jdk动态代理的缺点。CGLIBCode Generator Library是一个强大的、高性能的代码生成库。CGLib 采用了非常底层的字节码技术其原理是通过字节码技术为一个类创建子类并在子类中采用方法拦截的技术拦截所有父类方法的调用顺势织入横切逻辑。
Cglib 子类代理实现方法: 1.需要引入 cglib 的 jar 文件,但是 Spring 的核心包中已经包括了 Cglib 功能,所以直接引入 spring-core-xxx.jar 即可
2.引入功能包后,就可以在内存中动态构建子类 3.代理的类不能为 final,否则报错 4.目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
CGLIB 创建的动态代理对象比JDK 创建的动态代理对象的性能更高,但是 CGLIB创建代理对象时所花费的时间却比 JDK 多得多。所以对于单例的对象因为无需频繁创建对象用 CGLIB 合适反之使用 JDK 方式要更为合适一些。同时由于 CGLib 由于是采用动态创建子类的方法对于 final 修饰的方法无法进行代理。
/** 动态代理类*/
public class CGLibProxy implements MethodInterceptor {private Enhancer enhancer new Enhancer();public Object getProxy(Class? clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } /** 拦截所有目标类方法的调用 * 参数 * obj 目标实例对象 * method 目标方法的反射对象 * args 方法的参数 * proxy 代理类的实例 */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {//代理类调用父类的方法 System.out.println(开始事务); Object obj1 proxy.invokeSuper(obj, args); System.out.println(关闭事务); return obj1; }
}
//具体主题
public class UserDaoImpl{public void save() {System.out.println(UserDaoImpl:save());}
}
//测试类
public class Test {public static void main(String[] args) {CGLibProxy proxy new CGLibProxy(); UserDaoImpl userDaoImpl (UserDaoImpl) proxy.getProxy(UserDaoImpl.class);userDaoImpl.save();}
}