设计模式
一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。 项目中合理的运用设计模式可以巧妙的解决了面临的一般问题。
一 什么是设计模式?
(1)基本定义:设计模式(Design pattern)是一套被反复使用的代码设计经验的总结。使用设计模式的目的是为了可
重用代码、让代码更容易被他人理解。设计模式是是软件工程的基石脉络,如大厦的结构一样。
(2)Design pattern的四大要素:模式名称(Name),问题(Question),解决方案(Solution),效果(Efftive)。
(3)OO(面向对象)的六大原则:单一职责原则,开闭原则,里氏替换原则,依赖倒置原则,接口隔离原则,迪米特原则。
二 设计模式的分类
设计模式分为三种类型:
(1)创建型模式5种:单例模式,抽象工厂模式,工厂模式,原型模式,建造者模式。
(口诀:单原建造者,东西二厂)
(2)结构型模式7种:适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式。
(口诀:一器一桥一元一代理;装饰组合外观)
(3)行为型模式11种:观察者模式,中介者模式,访问者模式,解释器模式,迭代器模式,备忘录模式,责任链模式,状态模式,策略模式,命令模式,模板模式。
(口诀:三者两器、一录一链一模板,状态策略命令)
设计模式六大原则
一:单一职责原则
二:开闭原则:对修改关闭,对扩展开放
三:迪米特法则:一个软件的实体,应该尽量减少与其他实体的相互作用
四:接口隔离原则:应该使用多个接口,而不是使用一个总接口。
五:依赖倒转原则:抽象不依赖具体细节,细节依赖接口
六:里氏替换原则:所有引用父类的地方必须能使用子类对象
工厂模式:
工厂是专门用来生产产品的,而Java中工厂是专门用来生产对象的
简单工厂:
工厂类:简单工厂的核心,里面根据参数来绝对创建的对象
抽象:及简单工厂创建所有类的父类,或接口抽象
产品:及需要被简单工厂创建对象的实体类
备注:所有对象的实例化都由工厂类去完成。
优点:体积小,工厂只有一个类
缺点:违反OCP原则,每当业务扩展时,需要修改工厂类
方法工厂(工厂方法):(把对象的实例化工作推迟到了子类中)
抽象工厂:所有工厂的核心把,具体工厂必须继承或实现他
具体工厂:是抽象工厂的一种实现,负责对象的实例化
抽象:及简单工厂创建所有类的父类,或接口抽象
产品:及需要被简单工厂创建对象的实体类
优点:符合OCP原则,每当业务扩展时,不需要修改已有代码,只需要添加对应的实现类工厂即可。
缺点:体积大,如果业务庞大,工厂体积会特别大,因为一个工厂实体类只对应一个实体,方法工厂只针对一类产品,无法解决多类产品的问题。
抽象工厂:(了解即可,主要用于解决产品族的问题)
产品族:多个产品,相互依赖从而形成产品族的存在抽象工厂即是方法工厂的进化,如果只有一个产品,那就是方法工厂,当有多个产品存在时,即为抽象工厂
注意:我们使用工厂模式时,不需要去纠结于到底要用什么模式,根据我们的业务需求来绝对即可。工厂模式不要想的太复杂了,所谓的工厂模式,就是为了创建对象而存在
Proxy 代理模式
现实中的代理:
虽然产品是厂家直接生产的,但是厂家并不直接面对消费群众,而是交给代理,由代理负责出售产品.虽然代理的最终目的也是把厂家的商品卖出去,但是代理会在卖商品前后增加一些操作,如结账前的打折,与卖掉商品后送优惠券.
代码中的代理:
代码中的代理是,让业务层只关注自身业务的实现逻辑,保证代码的重要性.事实上所谓的代理,就是A类的事情让B类去做,B类有A类的所有功能,并能在起功能上进行扩展.
静态代理:
1)共同接口:让代理对象与真实对象具有相同的功能;
2)真实对象:真实对象有房子要出租,或有书要卖;
3)代理对象:代理对象是在把房子要租给你之前进行操作.
优点:让业务层只关注自身业务的实现逻辑,保证代码的重用性.
缺点:每增加一个真实对象,则需要增加一个代理对象,而且静态代理是针对方法的,如果类中的方法很多,
则需要对每一个方法都进行处理,如果接口增加一个方法,所有的真实对象都要添加这个方法,所有的代理
对象都要实现这个方法,增加了代码的维护性和复杂性.
JDK动态代理:
在JVM运行时,动态生成代理类,他提供了一组静态方法来为接口的代理对象.
主要方法:使用代理类的:
Proxy.newProxyInstance(proxy.getClass().getClassLoader(), new Class[] {BookStore.class}, proxy);
方法职责:为指定的类加载器,一组接口(因为多实现,单继承),及调用类,然后动态的给我们生成代理类的实例.
方法参数:类加载器 , 接口的class对象,InvocationHandler 代理执行处理器(代理类对象)
方法返回:动态生成的代理对象.
主要接口 InvocationHandler
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{}
方法职责:负责集中处理动态代理商的所有方法调用
方法参数:代理对象,当前调用方法的真实对象,方法参数
方法返回:真实方法的返回结果
JDK动态代理的操作步骤:
1)实现InvocationHandler接口,编写代理操作(创建自己的代码增强器).
2)给Proxy提供对应的参数,动态的创建代理对象.
一.JDK动态代理就是通过InvocationHandler接口与Proxy来完成.
二.使用JDK动态代理必须有接口
三.JDK动态代理是针对类的,所有的public方法都会被拦截.(接口中的方法都是public修饰的)
方法工厂:
// 抽象工厂
public abstract class PCFactory {
abstract Mouse getMouse();
abstract KeyBoard getKeyBoard();
}
// 鼠标接口
public interface Mouse {
// 生产鼠标
void createMouse();
}
// 键盘接口
public interface KeyBoard {
// 生产键盘
void createKryBorad();
}
//惠普工厂(具体工厂)
public class HPFactory extends PCFactory{
@Override
Mouse getMouse() {
return new HPMouse();
}
@Override
KeyBoard getKeyBoard() {
return new HPKeyBoard();
}
}
public class DellFactory extends PCFactory{
@Override
Mouse getMouse() {
return new DellMouse();
}
@Override
KeyBoard getKeyBoard() {
return new DellKeyboard();
}
}
// 惠普鼠标实现类
public class HPMouse implements Mouse{
@Override
public void createMouse() {
System.out.println("生产惠普鼠标");
}
}
// 惠普键盘实现类
public class HPKeyBoard implements KeyBoard{
@Override
public void createKryBorad() {
System.out.println("生产惠普键盘");
}
}
// 戴尔鼠标实现类
public class DellMouse implements Mouse{
@Override
public void createMouse() {
System.out.println("生产戴尔鼠标");
}
}
// 戴尔键盘实现类
public class DellKeyboard implements KeyBoard{
@Override
public void createKryBorad() {
System.out.println("生产戴尔键盘");
}
}