当前位置: 首页 > news >正文

做英德红茶的网站网站如何被收录

做英德红茶的网站,网站如何被收录,上海工作,创建一个网站流程图模式是一条由三部分组成的通用规则#xff1a;它代表了一个特定环境、一类问题和一个解决方案之间的关系。每一个模式描述了一个不断重复发生的问题#xff0c;以及该问题解决方案的核心设计。 软件领域的设计模式定义#xff1a;设计模式是对处于特定环境下#xff0c;经常… 模式是一条由三部分组成的通用规则它代表了一个特定环境、一类问题和一个解决方案之间的关系。每一个模式描述了一个不断重复发生的问题以及该问题解决方案的核心设计。 软件领域的设计模式定义设计模式是对处于特定环境下经常出现的某类软件开发问题的一种相对成熟的设计方案。 由来有资深的软件设计师它们积累了足够的经验这些经验让他们快速、优雅地解决软件开发中的大量重复问题。而设计模式的最终目标就是帮助人们利用软件设计师的集体经验从而设计出更加优秀的软件。 设计模式通产分为三类 创建型创建对象时不再直接实例化对象而是根据特定场景由程序来确定创建对象的方式从而保证更高的性能、更好的架构优势。主要有工厂模式简单工厂模式抽象工厂模式、单例模式、生成器模式和原型模式。结构型用于帮助将多个对象组织成更大的结构。主要有适配器模式、桥接模式、组合器模式、装饰器模式、门面模式、享元模式和代理模式。行为型用于帮助系统间个对象的通信以及如何控制复杂系统中的流程。主要有命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板模式和访问者模式。 设计模式五大原则 单一职责原则一个类应该只有一个引起它变化的原因。也就是说一个类只负责一个功能或任务从而实现高内聚、低耦合的设计。 开闭原则软件实体类、模块、函数等应该对扩展开放对修改关闭。也就是说当需要新增功能时应该通过扩展现有代码来实现而不是修改现有代码。 里氏替换原则任何时候子类都可以替换父类并且表现出类似的行为。也就是说在任何需要使用父类对象的地方都可以使用子类对象来替换而不会导致程序出错。 接口隔离原则一个类不应该强迫客户端调用它的代码依赖于它不需要的方法。也就是说一个接口应该只包含必要的方法而不应该包含不必要的方法。 依赖倒置原则高层模块不应该依赖底层模块二者都应该依赖抽象接口。也就是说依赖关系应该是通过抽象接口来实现而不是通过具体实现来实现。这样可以降低模块之间的耦合性提高代码的灵活性和可维护性。 1创建型设计模式 1.1单例模式 有些时候允许自由创建某个类的实例没有意义还可能造成系统性能下降因为创建对象会带来系统开销问题。在JAVA EE应用中可能只需要一个数据库引擎访问点Hibernate访问时只需要一个SessionFactory实例如果在系统中为它们创建多个实例就没有太大意义。如果一个类始终只能创建一个实例则这个类被称为单例类这种模式被称为单例模式。 单例和多例 你用杯子喝可乐喝完了不刷继续去倒果汁喝就是单例。你用杯子喝可乐直接扔了杯子换个杯子去倒果汁喝就是多例。用单例和多例的标准只有一个当对象含有可改变的状态时更精确的说就是在实际应用中该状态会改变则多例否则单例。 实现方式 为了保证该类只能产生一个实例程序不能允许自由创建该类的对象而是只允许为该类创建一个对象。为了避免程序自由创建该类的实例使用private修饰该类的构造器从而将该类的构造器隐藏起来。将该类的构造器隐藏起来则需要体用一个public方法作为该类访问点用于创建该类的对象且该方法必须使用static修饰因为调用该方法之前不存在对象因此调用该方法的不可能是对象只能是类。除此之外该类还必须缓存已经创建的对象否则该类无法知道是否曾经创建过实例也就无法保证只创建一个实例。为此该类需要使用一个静态属性来保证曾经创建的实例且该属性需要被静态方法访问所以该属性也应使用static修饰。 使用单例模式的优势 减少创建Java实例所带来的系统开销。便于系统跟踪单个Java实例的生命周期、实例状态。 懒汉式双重sync或者在instance变量加上volatile修饰 class Singleton {//使用一个类变量缓存曾经创建的实例private static Singleton instance;//将构造器使用private修饰隐藏该构造器private Singleton() {}//提供一个静态方法用于返回Singleton实例该方法可以加入自定义控制保证只产生一个Singleton对象synchronized public static Singleton getInstance() {//如果instance为null表明还不曾创建Singleton对象//如果instance不为null则表明已经创建了Singleton对象将不会执行该方法if (instance null) {synchronized (Singleton.class) {// 双重检查确保只有一个线程创建实例if (instance null) {instance new Singleton();}}}return instance;} } 饿汉式通过静态变量保证了线程安全 class Singleton {private static Singleton instance new Singleton();//私有化构造方法防止外部访问private Singleton() { }//通过共有的静态方法获取对象实例public static Singleton getInstance() {return instance;} } Java Web项目中的单例模式 数据库连接池就是单例模式有且仅有一个连接池管理者管理多个连接池对象。单例在spring中是默认的如果要产生多例则在配置文件的bean中添加scopeprototype。对于struts2来说action必须用多例因为action本身含有请求参数的值即可改变的状态Struts2会对每一个请求产生一个Action的实例来处理。如果是单例的话若出现两个用户都修改一个对象的属性值则会因为用户修改时间不同两个用户访问得到的属性不一样操作得出的结果不一样。有一块布长度300cm,能做一件上衣(用掉100cm)和一件裤子(用掉200cm);甲和乙同时访问得到的长度都是300cm,甲想做上衣和裤子,他先截取100cm去做上衣,等上衣做完再去做裤子,而乙这时正好也拿100cm去做上衣,那好,等甲做完上衣再做裤子的时候发现剩下的布(100cm)已经不够做裤子了…..这就是影响系统的性能,解决的办法就是给甲和乙一人一块300cm的布,就不会出现布被别人偷用的事情servlet采用单实例多线程模式开发减少产生servlet实例的开销当容器收到一个Servlet请求调度线程从线程池中选出一个工作者线程将请求传递给该工作者线程然后由该线程来执行Servlet的service方法。当这个线程正在执行的时候容器收到另外一个请求调度线程同样从线程池中选出另一个工作者线程来服务新的请求容器并不关心这个请求是否访问的是同一个Servlet。当容器同时收到对同一个Servlet的多个请求的时候那么这个Servlet的service()方法将在多线程中并发执行。 Spring推荐将所有业务逻辑组件、DAO组件、数据源组件等配置成单例的行为方式因为这些组件无须保存任何用户状态故所有客户端都可共享这些逻辑组件、DAO组件因此推荐讲这些组件配置成单例模式的行为方式。  1.2工厂模式 模式动机 在软件系统中经常面临着“某个对象”的创建工作由于需求的变化这个对象经常面临着剧烈的变化但是它却拥有比较稳定的接口。如何应对这种变化如何提供一种“封装机制”来隔离出“这个易变对象”的变化从而保持系统中“其他依赖该对象的对象”不随着需求改变而改变。当你需要什么只需要传入一个正确的参数就可以获取你所需要的对象而无须知道其创建细节。 工厂模式的用意是定义一个创建产品对象的工厂接口将实际创建性工作推迟到子类中。工厂模式可分 为简单工厂、工厂方法和抽象工厂模式。 注意我们常说的23种经典设计模式包含了工厂方法模式和抽象工厂模式而并未包含简单工厂模式。另外我们平时说的工厂模式一般默认是指工厂方法模式。 1.3简单工厂 简单工厂模式其实并不算是一种设计模式更多的时候是一种编程习惯。简单工厂的实现思路是定义 一个工厂类根据传入的参数不同返回不同的实例被创建的实例具有共同的父类或接口。增加新产品时需要修改工厂类、增加产品类。 使用简单工厂模式的优势让对象的调用者和对象创建过程分离当对象调用者需要对象时直接向工厂请求即可。从而避免了对象的调用者与对象的实现类以硬编码方法耦合以提高系统的可维护性、可扩展性。 简单工厂模式的缺点当产品修改时工厂类也要做相应的修改。  简单工厂的适用场景  工厂类负责创建的对象比较少客户只知道传入工厂类的参数对于如何创建对象逻辑不关心由于简单工厂很容易违反高内聚责任分配原则因此一般只在很简单的情况下应用。  简单工厂的使用场景  日志记录器记录可能记录到本地硬盘、系统事件、远程服务器等用户可以选择记录日志到什么地方。 数据库访问当用户不知道最后系统采用哪一类数据库以及数据库可能有变化时。 设计一个连接服务器的框架需要三个协议POP3、IMAP、HTTP可以把这三个作为产品类共同实现一个接口。 简单工厂包含的角色 Factory工厂工厂类在客户端的直接调用下创建产品对象它往往是由一个具体的java类实现。Product抽象产品担任模式所创建的对象的父类或它们的共同的接口抽象产品角色可以用一个java接口或者java抽象类实现。ConcreteProduct具体产品所创建的任何对象都是这个角色实例具体产品角色是由一个具体的java类实现。 【问题】创建一个可以绘制不同形状的绘图工具可以绘制圆形正方形三角形每个图形都会有一个draw() 方法用于绘图不看代码先考虑一下如何通过该模式设计完成此功能。 【分析】由题可知圆形正方形三角形都属于一种图形并且都具有draw方法所以首先可以定义一个接口 或者抽象类作为这三个图像的公共父类并在其中声明一个公共的draw方法 抽象产品 public interface Shape {void draw(); }具体产品 //圆形 class CircleShape implements Shape{public CircleShape(){System.out.println(CircleShape: create);}public void draw() {System.out.println(draw: CircleShape);} } //正方形 class RectShape implements Shape{public RectShape(){System.out.println(RectShape: create);}public void draw() {System.out.println(draw: RectShape);} } //三角形 class TriangleShape implements Shape{public TriangleShape(){System.out.println(TriangleShape: create);}public void draw() {System.out.println(draw: TriangleShape);} } 工厂 class ShapeFactory {public static Shape getShape(String type) {Shape shape null;if (type.equalsIgnoreCase(circle)) {shape new CircleShape();} else if (type.equalsIgnoreCase(rect)) {shape new RectShape();} else if (type.equalsIgnoreCase(triangle)) {shape new TriangleShape();}return shape;} } 为工厂类传入不同的type可以new不同的形状返回结果为Shape 类型这个就是简单工厂核心的地方了。 1.4工厂方法 工厂方法模式工厂方法模式是简单工厂的仅一步深化 在工厂方法模式中我们不再提供一个统一的工厂类来创建所 有的对象而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。 工厂方法的实现思路定义一个用于创建对象的接口让子类决定将哪一个类实例化。工厂方法模式 让一个类的实例化延迟到其子类。  工厂方法适用场景 客户端不需要知道它所创建的对象的类。 客户端可以通过子类来指定创建对应的对象。 模式定义 工厂方法模式去掉了简单工厂模式中工厂方法的静态属性使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。工厂方法模式又称为工厂模式在该模式中工厂父类负责定义创建产品对象的公共接口而工厂子类则负责生成具体的产品对象这样可以将产品类的实例化操作延迟到工厂子类中完成即通过工厂子类来确定究竟应该实例化哪一个具体产品。 简单工厂包含的角色 Product抽象产品它是具体产品继承的父类或者是实现的接口。在 java 中一般有抽象类或者接口来实现。ConcreteProduct具体产品具体工厂角色所创建的对象就是此角色的实例。在 java 中由具体的类来实现。Factory抽象工厂这是工厂方法模式的核心它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在 java 中它由抽象类或者接口来实现。ConcreteFactory具体工厂它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 【问题】现在需要设计一个这样的图片加载类它具有多个图片加载器用来加载jpgpnggif格式的图片 每个加载器都有一个read()方法用于读取图片。下面我们完成这个图片加载类。 简单工厂-抽象产品 public interface Reader {void read(); } 简单工厂-具体产品 class JpgReader implements Reader{public void read() {System.out.println(read jpg);} } class PngReader implements Reader{public void read(){System.out.println(read png);} } class GifReader implements Reader{public void read(){System.out.println(read gif);} } 抽象工厂-抽象产品 interface ReaderFactory{Reader getReader(); } 简单工厂-具体产品 // jpg加载器工厂 class JpgReaderFactory implements ReaderFactory {Overridepublic Reader getReader() {return new JpgReader();} } // png加载器工厂 class PngReaderFactory implements ReaderFactory {Overridepublic Reader getReader() {return new PngReader();} } // gif加载器工厂 class GifReaderFactory implements ReaderFactory {Overridepublic Reader getReader() {return new GifReader();} } 在每个工厂类中我们都通过重写的getReader()方法返回各自的图片加载器对象。和简单工厂对比一下最根本的区别在于简单工厂只有一个统一的工厂类而工厂方法是针对每个要 创建的对象都会提供一个工厂类这些工厂类都实现了一个工厂基类。 1.5抽象工厂 这个模式最不好理解而且在实际应用中局限性也蛮大的因为这个模式并不符合开闭原则。实际开发 还需要做好权衡。抽象工厂模式是工厂方法的仅一步深化在这个模式中的工厂类不单单可以创建一个对象而是可以创建一组对象。这是和工厂方法最大的不同点。 抽象工厂的实现思路是提供一个创建一系列相关或相互依赖对象的接口而无须指定它们具体的类。 抽象工厂和工厂方法一样可以划分为4大部分 AbstractFactory抽象工厂声明了一组用于创建对象的方法注意是一组。 ConcreteFactory具体工厂它实现了在抽象工厂中声明的创建对象的方法生成一组具体对象。 AbstractProduct抽象产品它为每种对象声明接口在其中声明了对象所具有的业务方法。ConcreteProduct具体产品它定义具体工厂生产的具体对象。 抽象工厂适用场景 和工厂方法一样客户端不需要知道它所创建的对象的类。 需要一组对象共同完成某种功能时。并且可能存在多组对象完成不同功能的情况。系统结构稳定不会频繁的增加对象。 至于Spring IoC容器到底是简单工厂还是抽象工厂我倾向于认为Spring IoC是抽象工厂因为Spring IoC容器可以包括万象它不仅可以管理普通Bean实例也可管理工厂实例。不用过于纠结于简单工厂模式、抽象工厂模式这些概念可以把他们统称为工厂模式。如果工厂直接生产被调用对象那就是简单工厂模式如果工厂生产了工厂对象那就回升级成抽象工厂模式。 【问题】现在需要做一款跨平台的游戏需要兼容AndroidIosWp三个移动操作系统该游戏针对每个系统 都设计了一套操作控制器OperationController和界面控制器UIController下面通过抽闲工厂 方式完成这款游戏的架构设计。 【分析】由题可知游戏里边的各个平台的UIController和OperationController应该是我们最终生产的具体产品。所以新建两个抽象产品接口。 抽象操作控制器抽象界面控制器 interface OperationController{void control(); } interface UIController{void display(); } 然后完成各个系统平台的具体操作控制器和界面控制器AndroidIOSWP class AndroidOperationController implements OperationController {public void control() {System.out.println(AndroidOperationController);} }class AndroidUIController implements UIController {public void display() {System.out.println(AndroidInteraceController);} }class IosOperationController implements OperationController {public void control() {System.out.println(IosOperationController);} }class IosUIController implements UIController {public void display() {System.out.println(IosInterfaceController);} } class WpOperationController implements OperationController {public void control() {System.out.println(WpOperationController);} }class WpUIController implements UIController {public void display() {System.out.println(WpInterfaceController);} } 下面定义一个抽闲工厂该工厂需要可以创建OperationController和UIController。 public interface SystemFactory {public OperationController createOperationController();public UIController createInterfaceController(); }在各平台具体的工厂类中完成操作控制器和界面控制器的创建过程。 class AndroidFactory implements SystemFactory {public OperationController createOperationController() {return new AndroidOperationController();}public UIController createInterfaceController() {return new AndroidUIController();} } class IosFactory implements SystemFactory{public OperationController createOperationController() {return new IosOperationController();}public UIController createInterfaceController() {return new IosUIController();} } class wpFactory implements SystemFactory{public OperationController createOperationController() {return new WpOperationController();}public UIController createInterfaceController() {return new WpUIController();} } 简单工厂模式和抽象工厂模式有什么区别 1简单工厂模式其实并不算是一种设计模式更多的时候是一种编程习惯。简单工厂的实现思路是定义 一个工厂类根据传入的参数不同返回不同的实例被创建的实例具有共同的父类或接口。 2工厂方法模式是简单工厂的仅一步深化 在工厂方法模式中我们不再提供一个统一的工厂类来创建所 有的对象而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。工厂方 法的实现思路是定义一个用于创建对象的接口让子类决定将哪一个类实例化。工厂方法模式让一个 类的实例化延迟到其子类。 3抽象工厂模式是工厂方法的仅一步深化在这个模式中的工厂类不单单可以创建一个对象而是可以创 建一组对象。这是和工厂方法最大的不同点。抽象工厂的实现思路是提供一个创建一系列相关或相互 依赖对象的接口而无须指定它们具体的类。 2结构型设计模式 2.1代理模式 代理模式是一种应用非常广泛的设计模式当客户端代码需要调用某个对象时客户端实际上也不关心是否准确得到对象它只要一个能提供该功能的对象即可此时就可返回该对象的代理Proxy。 这种设计方式下系统为某个对象提供一个代理对象并由代理对象控制对源对象的应用。代理就是一个Java对象代表另一个Java对象来采取行动。在某些情况下客户端代码不想或不能够直接调用被调用者代理对象可以在客户和目标对象之间起到中介作用。 对于客户端而言它不能分辨出代理对象与真实对象的区别它也无须分辨代理对象和真实对象的区别客户端代码并不知道真正的被代理对象客户端代码面向接口编程它仅仅持有一个被代理对象的接口。 总而言之只要客户端代码不能或不想直接访问被调用对象——这种情况有很多原因比如需要创建一个系统开销很大的对象或者被调用对象在远程主机上或者目标对象的功能还不足以满足需求......而是额外创建一个代理对象返回给客户端使用那么这种设计模式就是代理模式。 代理模式的作用阻止对目标对象的直接访问或者就是在执行目标对象时在执行目标对象前后进行一系列的操作。举个例子来说1在执行一个方法之前必须要对该“方法”做“日记”记录每个操作这样可以在执行目标对象之前先执行一个的操作然后执行该方法。2又如明星唱歌例子商家首先找到该明星的代理公司谈妥后再找该明星去唱歌中间代理起拦截等的操作。 代理模式包含如下角色 Subject抽象主题角色声明了真实主题和代理主题的共同接口。Proxy代理主题角色内部包含对真实主题的引用并且提供和真实主题角色相同的接口。RealSubject真实主题角色定义真实的对象。 静态代理手动添加被代理对象的方法。 写一个普通类继承目标对象的接口。写一个实例变量记住代理谁即目标对象。使用构造方法为实例变量赋值或者可以直接赋值。写一个普通方法该方法的返回值是接口该接口是目标对象的实现接口。 //歌迷 public class Fans {public static void main(String[] args) {//创建代理对象ZhangYuProxy zhangyuProxy new ZhangYuProxy();//通过代理对象找目标对象//业务方法zhangyuProxy.sing(30000);} } ------------------------------------------------- public interface Star {public void sing(int m); } ------------------------------------------------- public class ZhangYu implements Star {public void sing(int m) {System.out.println(宇哥唱歌);} } ------------------------------------------------- public class ZhangYuProxy implements Star {private ZhangYu zhangyu new ZhangYu();public void sing(int m) {if(m3000)zhangyu.sing(m);elseSystem.out.println(出场费不足);}//基于接口编程public Star getProxy() {return zhangyu;} } 这种静态代理的方法不推荐使用分析一下如果说star里面有多少个方法在代理对象的类中就有多少个方法。不利于扩展。举个例子如果说在A类是目标对象B类是代理对象A类每个方法执行前都需要做”日志“操作那么代理对象需要扩展A类所有方法在执行前加上日志的代码。当A类增加方法时B类仍然要手动添加一个方法做”日志“。所以这里不推荐使。 动态代理自动生成被代理对象的方法无须手动生成。 通过实现 InvocationHandler 接口创建自己的调用处理器。通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类。通过反射机制获得动态代理类的构造函数其唯一参数类型是调用处理器接口类型。通过构造函数创建动态代理类实例构造时调用处理器对象作为参数被传入。 为了简化对象创建过程Proxy类中的newProxyInstance方法封装了2~4只需两步即可完成代理对象的创建。 代理对象的生成是利用JDKAPI 动态的在内存中构建代理对象。Proxy类与普通类的唯一区别就是其字节码是由JVM在运行时动态生成的而非预存在于任何一个.class文件中。每次生成动态代理类对象时都需要指定一个类装载器对象newProxyInstance()方法第一个参数。 1Proxy类Proxy类提供了用于创建动态代理类和实例对象的方法它是所创建的动态代理类的父类它最常用的方法如下 public static Class getProxyClass(ClassLoader loader,Class[] interfaces)该方法用于返回一个Class类型的代理类在参数中需要提供类加载器并需要指定代理的接口数组与真实主题类的接口列表一致。public Static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)该方法用于返回一个动态创建的代理类的实例方法中第一个参数loader表示代理类的类加载器第二个参数interfaces表示代理类所实现的接口列表与真实主题类的接口列表一致第三个参数h表示所指派的调用处理程序类。 2InvocationHandler接口InvocationHandler接口是代理处理程序类的实现接口该接口作为代理实例的调用处理者的公共父类每一个代理类的实例都可以提供一个相关的具体调用处理者InvocationHandler接口的子类。在该接口中声明了如下方法 public Object invoke(Object proxy, Method method, Object[] args)该方法用于处理对代理的类实例的方法调用并返回相应的结果当一个代理实例中的业务方法被调用时将自动调用该方法。invoke()方法包含三个参数其中第一个参数proxy表示代理的类的实例第二个参数method表示需要代理的方法第三个参数args表示代理方法的参数数组。 动态代理类需要在运行时指定所代理真实主题类的接口客户端在调用动态代理对象的方法时调用请求会将请求自动转发给InvocationHandler对象的invoke()方法由invoke()方法来实现对请求的统一处理。 //哥/歌迷 public class Fans {public static void main(String[] args) {//创建代理对象ZhangYuProxy zhangyuProxy new ZhangYuProxy();//通过代理对象找目标对象Star star zhangyuProxy.getProxy();//业务方法star.sing(30);//业务方法star.dance(5,恰恰舞);//业务方法star.eat(8);} } ----------------------------------------------------- //接口 public interface Star {public void sing(String money);public void dance(String money,String what);public void eat(String money);} ----------------------------------------------------- //目标对象 public class ZhangYu implements Star {public void sing(String money) {System.out.println(宇哥唱歌);}public void dance(String money, String what) {System.out.println(宇哥跳舞名称为 what);}public void eat(String money) {System.out.println(宇哥吃饭);} } ----------------------------------------------------- import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //代理类 public class ZhangYuProxy{ //代理谁通过构造方法赋值private ZhangYu zhangyu new ZhangYu();//动态产生代理对象public Star getProxy(){return (Star) Proxy.newProxyInstance(ZhangYuProxy.class.getClassLoader(), zhangyu.getClass().getInterfaces(), new InvocationHandler(){public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {String money (String) args[0];System.out.println(method.getName()在调用);if(sing.equals(method.getName())){if(new Integer(money)3){//调用宇哥的sing()方法return method.invoke(zhangyu,args);}else{System.out.println(不够出场费); }}else if(dance.equals(method.getName())){if(new Integer(money)5){return method.invoke(zhangyu,args);}else{System.out.println(不够出场费); }}else if(eat.equals(method.getName())){System.out.println(宇哥今天有事不能来);}return null;}});} } //参数一loader表示动态代理对象是由哪个类加载器完成的 //参数二interfaces表示动态代理对象与目标对象宇哥有一样的方法 //参数三表示动态代理对象的栏截方法即每次调用目标对象都会执行该invoke()方法(难点)//invoke()方法的三个参数含义如下 //参数一动态产生的代理对象本身 //参数二method表示方法 //参数三args表示方法参数【案例】Spring框架中的AOP技术基于代理模式。 组成  调用者Beans - 即调用发起者它只知道目标方法所在Bean并不清楚代理以及Advice的存在。目标方法所在Bean - 被调用的目标方法。生成的代理 - 由Spring AOP为目标方法所在Bean生成的一个代理对象。Advice - 切面的执行逻辑。 过程 调用者Bean尝试调用目标方法但是被生成的代理截了胡。代理根据Advice的种类(本例中是Before Advice)对Advice首先进行调用。代理调用目标方法。返回调用结果给调用者Bean(由代理返回没有体现在图中)。 【案例】Hibernate延迟加载所采用的的设计模式Hibernate关联映射时。 当A实体与B实体之间存在关联关系时Hibernate默认启用延迟加载当系统加载A实例时A实例关联B实例的B实例并未被加载出来A实体所关联的B实体全部是代理对象——只有等到A实体真正需要访问B实体时系统才会去数据库里抓取B实体所对应的记录。 【案例】Struts2中的AOP实现 大部分web应用都涉及权限控制当浏览者需要执行某个操作时应用需要先检查浏览者是否登录以及是否有足够的权限来执行该操作。 本示例要求用户登录必须为制定用户名才可以查看系统中某个视图资源否则直接转入登录页面。对于上面的需求可以在每个action执行业务逻辑之前先执行权限检查逻辑但这种做法不利于代码复用。因为大部分action中检查权限代码都大同小异故将这些代码逻辑放在拦截器中将会更加优雅。 检查用户是否登录通常都是跟踪用户的Session来完成的通过ActionContext即可访问到Session中的属性拦截器的intercep(ActionInvocation invocation)方法的invocation参数可以很轻易的访问到请求相关的ActionContex实例。 2.2装饰器模式 代理模式是一种结构型模式它通过使用一个代理对象来控制对实际对象的访问。在这种模式下客户端通过与代理对象交互来访问实际对象从而使得代理对象可以在访问前或访问后加入一些额外的处理逻辑。代理模式常被应用于需要控制或限制对某个对象的访问或者需要在访问前后执行额外的逻辑的场合。 装饰器模式也是一种结构型模式它允许动态地向一个现有对象添加新的功能同时又不改变其结构。在这种模式下我们可以创建一个装饰器类该类包装了实际对象并提供了额外的功能。装饰器模式常被应用于需要动态地修改对象的行为或增加对象的功能的场合。 两种模式的主要异同点如下 目的不同代理模式的主要目的是控制或限制对某个对象的访问或在访问前后执行额外的逻辑而装饰器模式的主要目的是动态地修改对象的行为或增加其功能。 装饰器模式更加灵活装饰器模式允许我们动态地为一个对象添加功能而代理模式则更多地是控制或限制已有的对象的访问。因此装饰器模式更加灵活可以随时动态地为对象添加/删除功能而代理模式则需要预先声明代理对象。 装饰器模式中的装饰器可叠加在装饰器模式中我们可以创建多个装饰器类它们可以按照一定的规划来组合从而实现更丰富的功能。而在代理模式中我们只能使用一个代理对象。 2.3门面模式 随着系统的不断改进和开发他们会变得越来越复杂系统会生成大量的类这使得程序流程更难被理解。门面模式可为这些类提供一个简单的接口从而简化访问这些类的复杂性有时这种简化可能降低访问这些底层的灵活性但除了要求特别苛刻的客户端之外它通常都可以提供所需的全部功能。 门面模式也被称为正面模式、外观模式这种模式用于将一组复杂的类包装到一个简单的外部接口中。 场景有一个顾客需要到饭店用餐这就需要定义一个Customer类并为该类定义一个havaDinner()方法。考虑该饭店有三个部门收银部、厨师部和服务商部用户就餐需要这三个部门协调才能完成。 public class Payment {public String pay(){String food 快餐;System.out.println(你已经向收银员支付了费用您购买的是food);return food;} } ---------------------------------- public class Cook {public String cook(String food) {System.out.println(厨师蒸菜烹饪 food);return food;} } ---------------------------------- public class Waiter {public void server(String food) {System.out.println(服务生已将 food 端过来了请慢用...);} }public class Customer {public void haveDinner() {Payment pay new Payment();Cook cook new Cook();Waiter waiter new Waiter();String food pay.pay();food cook.cook(food);waiter.server(food);} }Customer需要依次调用三个部门的方法才可实现这个haveDinner()方法。如果这个饭店有更多的部门那么程序就需要调用更多部门的方法来实现这个haveDinner()方法——这就会增加haveDinner()方法的实现难度了。 为了解决这个问题可以为Payment、Cook、Writer三个部门提供一个门面Facade使用该Facade来包装这个类对外提供一个简单的访问方法。 public class Facade {Payment pay;Cook cook;Waiter waiter;public Facade() {this.pay new Payment();this.cook new Cook();this.waiter new Waiter();}public void serverFood() {String food pay.pay();food cook.cook(food);waiter.server(food);} }该门面类保证了Payment、Cook、Waiter三个部门serverFood()方法对外提供了一个用餐方法而底层则依赖于三个部门的pay()、cook()、server()三个方法。如果不采用门面模式客户端需要自行决定需要调用那些类、那些方法并需要合理的顺序来调用它们才可实现所需的功能。 2.4桥接模式 桥接模式是一种结构型模式它主要应对的是由于实际的需要某个类具有两个或两个以上的维度变化如果只是使用继承将无法实现这种需要或者使得设计变得相当臃肿。 场景假设现在需要为某个餐厅制造菜单餐厅供应牛肉面、猪肉面而且顾客可以根据自己的口味选择是否添加辣椒。此时就产生了一个问题如何应对这种变化是否需要定义辣椒牛肉面、无辣牛肉面、辣椒猪肉面、无辣猪肉面4个子类如果有其他种类的面种和不同的辣度那岂不是要一直忙于定义子类 为了解决这个问题可以使用桥接模式桥接模式的做法是把变化部分抽象出来使变化部分与主类分离开来从而将多个维度的变化彻底分离。最后提供一个管理类来组合不同维度上的变化通过这种组合来满足业务的需求。 public interface Peppery {String style(); }public class PepperyStyle implements Peppery{public String style() {return 辣味很重很过瘾;} }public class PlainStyle implements Peppery{public String style() {return 味道清淡很养胃;} }从上面可以看出该Peppery接口代表了面条在辣味风格这个维度上的变化不论面条在该维度上有多少种变化程序只需要为这几种变化分别提供实现类即可。对于系统而言辣味风格这个维度上的变化时固定的程序必须面对的程序使用桥接模式将辣味风格这个维度的变化分离出来避免与牛肉、猪肉材料风格这个维度的变化耦合在一起。 程序还需要一个AbstractNoodle抽象类该抽象类将会持有一个Peppery属性该属性代表该面条的辣味风格。 public abstract class AbstractNoodle {protected Peppery style;public AbstractNoodle(Peppery style){this.style style;}public abstract void eat(); }--------------------------------------------- public class PorkyNoodle extends AbstractNoodle {public PorkyNoodle(Peppery style) {super(style);}public void eat() {System.out.println(这是一碗猪肉面条 super.style.style());} } --------------------------------------------- public class BeefNoodle extends AbstractNoodle {public BeefNoodle(Peppery style) {super(style);}public void eat() {System.out.println(这是一碗牛肉面 super.style.style());} }public class Main {public static void main(String[] args) {//辣味牛肉面AbstractNoodle noodle1 new BeefNoodle(new PepperyStyle());//不辣猪肉面AbstractNoodle noodle2 new PorkyNoodle(new PlainStyle())} }3行为型设计模式 3.1命令模式 假如存在某个场景某个方法需要完成某一个功能完成这个功能的大部分步骤已经确定了但可能有少量具体步骤无法确定必须等到执行该方法时才可以确定。具体来说假设有个方法需要遍历某个数组元素但无法确定在遍历元素时如何处理这些元素需要在调用该方法时指定具体的处理行为。这个方法不仅要求参数可以变化甚至要求方法执行体的代码可以变化需要能把“处理行为”作为一个参数传入该方法。 对于这样的需求要求把“处理行为”作为参数传入该方法而“处理行为”用编程来实现就是一段代码。在Java语言中类才是一等公民方法不能独立存在所以实际传入该方法的应该是一个对象该对象通常是某个接口的匿名实现类的实例该接口通常被称为命令接口这种设计模式被称为命令模式。 public interface Command {void process(int[] target); }public class ProcessArray {//定义一个each()方法用于处理数组public void each(int[] target, Command cmd) {cmd.process(target);} }public class Main {public static void main(String[] args) {ProcessArray pa new ProcessArray();int[] target {3, -4, 6, 4};pa.each(target, new Command() {public void process(int[] target) {for (int tmp : target) {System.out.println(迭代输出目标数组的元素 tmp);}}});pa.each(target, new Command() {public void process(int[] target) {int sum 0;for (int tmp : target) {sum tmp;}System.out.println(数组元素的总和是 sum);}});} }这样就实现了process()方法和”处理行为“的分离两次不同的处理行为分别由不同的Command对象来提供。  命令模式在MVC中的应用Struts中在模型层都要继承一个Action接口并实现execute方法其实这个Action就是命令类。为什么Struts会应用命令模式是因为Struts的核心控制器ActionServlet只有一个相当于Invoker(调用者)而模型层的类会随着不同的应用有不同的模型类相当于具体的Command。这样就需要在ActionServlet和模型层之间解耦而命令模式正好解决这个问题。 3.2策略模式 策略模式用于封装系列的算法这些算法通常被封装在一个被称为Context的类中客户端程序可以自由选择其中一种算法或让Context为客户端选择一个最佳的算法——使用策略模式的优势为了支持算法的自由切换。 场景加入正在开发一个网上书店该书店为了更好地促销经常需要对图书馆进行打折促销程序需要考虑各种打折促销的计算方法。 public double discount(double price) {switch (getDiscontType()){case VIP_DISCOUNT:return vipDiscount(price);break;case OLD_DISCOUNT:return oldDiscount(price);break;}} 这段代码没有太大问题但有明显的不足程序中各种打折方法都被直接写入discount(double price)方法中。如果有一天新增打折方法就需要修改三处地方1首先增加常量代表打折类型。2在switch中增加一个case语句。3需要实现xxxDiscount()方法。 public interface DiscountStrategy {double getDiscount(double originPrice); }public class VipDiscount implements DiscountStrategy {public double getDiscount(double originPrice) {System.out.println(使用VIP打折算法...);return originPrice * 0.5;} }public class OldDiscount implements DiscountStrategy {public double getDiscount(double originPrice) {System.out.println(使用默认打折...);return originPrice * 0.7;} }提供了两个折扣策略之后程序还需要提供一个DiscountContext类该类用于为客户端代码选择合适折扣策略当然也允许用户自由选择折扣策略。 public class DiscountContext {private DiscountStrategy strategy;public DiscountContext(DiscountStrategy strategy) {this.strategy strategy;}public double getDiscountPrice(double price) {if (strategy null) {strategy new OldDiscount();}return this.strategy.getDiscount(price);}public void changeDiscount(DiscountStrategy strategy){this.strategy strategy;} }public class Main {public static void main(String[] args) {DiscountContext dc new DiscountContext(null);double pricel 79;System.out.println(78元默认打折后的价格 dc.getDiscountPrice(pricel));dc.changeDiscount(new VipDiscount());System.out.println(78元VIP打折后的价格 dc.getDiscountPrice(pricel));} }使用默认打折... 78元默认打折后的价格55.3 使用VIP打折算法... 78元VIP打折后的价格39.5 再次考虑前面的需求当业务需要新增一种打折类型时系统只需要重新定义一个DiscountStrategy实现类该实现类实现getDiscount()方法用于实现新的打折算法即可。客户端程序需要切换为新的打折策略时则需要先调用DiscountContext的changeDiscount()方法切换为新的打折策略。 3.3观察者模式 观察者模式定义了对象间的一对多依赖关系让一个或多个观察者对象观察一个主题对象当主题对象的状态发生改变时系统能通知所有的依赖于此对象的观察者对象从而使得观察者对象能够自动观察。被观察的对象/被依赖的对象常常被称为目标或主题依赖的对象被称为观察者 public interface Observer {void update(Observable o, Object arg); } ------------------------------------------ import java.util.ArrayList; import java.util.List;public class Observable {//用一个List来保存该对象上所有绑定的事件监听器ListObserver observers new ArrayList();public void registObserver(Observer o){observers.add(o);}public void removeObserver(Observer o){observers.remove(o);}public void notifyObservers(Object value){for (Observer o:observers){o.update(this,value);}} }registObserver()方法用于注册一个新的观察者并提供了removeObserver()方法用于删除一个已注册的观察者当具体被观察对象的状态改变时具体被观察对象调用notifyObservers()方法来通知所有观察者。 public class Product extends Observable{private String name;private double price;public Product(){}public Product(String name,double price){this.name name;this.price price;}public String getName() {return name;}public void setName(String name) {this.name name;notifyObservers(name);}public double getPrice() {return price;}public void setPrice(double price) {this.price price;notifyObservers(price);} }提供两个观察者一个用于观察Product对象的name成员变量另一个用于观察Product对象的price成员变量。 import javax.swing.*;public class NameObserver implements Observer {public void update(Observable o, Object arg) {if (arg instanceof String) {String name (String) arg;JFrame f new JFrame(观察者);JLabel l new JLabel(名称改变为 name);f.add(l);f.pack();f.setVisible(true);System.out.println(名称观察者 o 物品名称已改变为 name);}} } ----------------------------------------- public class PriceObserver implements Observer {public void update(Observable o, Object arg) {if (arg instanceof Double){System.out.println(价格观察者 o 物品价格变为 arg);}} }public class Main {public static void main(String[] args) {Product p new Product(电视机,176);NameObserver no new NameObserver();PriceObserver po new PriceObserver();p.registObserver(no);p.registObserver(po);p.setName(书桌);p.setPrice(50);} }可以看到当Product的成员变量发生改变时注册在该Product上的NameObserver和PriceObserver将被触发。 可以发现观察者模式通常包含4个角色 被观察者的抽象基类它通常持有多个观察者对象的引用。Java提供了java.util.Observable基类来代表被观察者的抽象基类所以实际开发中无须自己开发这个角色。观察者接口该接口是所有被观察对象应该实现的接口通常它只包含一个抽象方法update()。Java同样提供了java.util.Observer接口来代表观察者接口实际开发中也无须开发该角色。被观察者实现类该类继承Observable基类。观察者实现类实现Observer接口实现update()抽象方法。
http://www.w-s-a.com/news/236597/

相关文章:

  • 2018新网站做外链app制作的网站
  • 外贸网站建设怎么建设pc网站做移动端适配
  • 做经销找厂家好的网站个人备案网站可以做电影站吗
  • 网站搭建怎么做网站建设培训哪家好
  • 学做美食的视频网站企业网站备案密码怎么找回
  • 销售产品做单页还是网站seo有哪些作用
  • 网站视觉规范南宁网站优化推广
  • 公司起名打分最准的免费网站学设计的学校
  • 用cn作网站行么WordPress网站打不开nginx
  • 顺德龙江网站建设百货商城自助下单网站
  • 门户网站采用较多的模式是wordpress自动搜索缩略图
  • 深圳设计功能网站做网站推广怎么做
  • 海口专业网站建设地址wordpress站点标题是什么
  • 青岛做网站那家好网页素材网
  • 宁夏银川做网站的公司网络营销有哪些推广方法
  • 免费域名网站哪个最好东莞企业网站排名
  • dz做网站网址模版
  • 做外贸网站平台中华室内设计师网
  • 三大网络架构seo是啥职业
  • 一个域名可以做中英文两个网站吗搜索引擎营销的6种方式
  • 可以做ppt的网站天津网站建设怎么样
  • 网站怎么做的qq邮件订阅浙江省住房和城乡建设厅网站查询
  • 主机屋网站在线做图片
  • 河南省城乡住房建设厅网站wordpress登陆密码
  • 漳州做网站的公司搭建网站多少时间
  • 网站开发实习计划模板微营销手机
  • 网站设计与制作是做什么工作免费封面设计在线制作生成
  • 网站开发的教学课程网站广告调词软件
  • 进下加强新闻宣传网站建设入门 做网站 书籍
  • 电商网站主题photolux wordpress