Java设计模式(1-8)_第1页
Java设计模式(1-8)_第2页
Java设计模式(1-8)_第3页
Java设计模式(1-8)_第4页
Java设计模式(1-8)_第5页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Java之美-设计模式 (Design pattern)-由菜鸟到高手演变什么是设计模式什么是设计模式可复用面向对象软件的基础是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性设计模式的分类设计模式的分类总体分为三大类:创建型模式,共 5 种:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。结构型模式,共 7 种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。行为型模式,共 11 种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模

2、式、访问者模式、中介者模式、解释器模式。1、单例模式(单例模式(Singleton)单例模式有以下特点:1、单例类只能有一个实例。2、单例类必须自己创建自己的唯一实例。3、单例类必须给所有其他对象提供这一实例。主要介绍:懒汉式单例、饿汉式单例。(1)懒汉式单例/ 懒汉式单例类.在第一次调用的时候实例化自己 public class Singleton private Singleton() private static Singleton single=null; / 静态工厂方法 public static Singleton getInstance() if (single = null)

3、 single = new Singleton(); return single; A、在getInstance方法上加同步public static synchronized Singleton getInstance() if (instance = null) instance = new Singleton(); return instance; B、双重检查锁定public static Singleton getInstance() if (instance = null) synchronized (instance) if (instance = null) instance

4、= new Singleton(); return instance; C、静态内部类public class Singleton private Singleton() /* 此处使用一个内部类来维护单例 */ private static class SingletonFactory private static Singleton instance = new Singleton(); public static Singleton getInstance() return SingletonFactory.instance; (2)饿汉式单例/ 饿汉式单例类.在类初始化时,已经自行实例

5、化 public class Singleton1 private Singleton1() private static final Singleton1 single = new Singleton1(); / 静态工厂方法 public static Singleton1 getInstance() return single; 单例模式应用场景单例模式应用场景网站的计数器,一般也是采用单例模式实现,否则难以同步。如:统计在线人数应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。Web应用的配置对象的读取,

6、一般也应用单例模式,这个是由于配置文件是共享的资源。数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。2、工厂方法模式(工厂方法模式(Factory Method)普通工厂模式多个工厂方法模式静态工厂方法模式(1)简单简单工厂工厂模式模式建立一个工厂类,对实现了同一接口的一些类进行实例的创建。关系图:举例:发送邮件和短信的例子public interface Sender public void Send(); public class MailSender implements Send

7、er Override public void Send() System.out.println(this is mailsender!); public class SmsSender implements Sender Override public void Send() System.out.println(this is sms sender!); / 工厂类工厂类public class SendFactory public Sender produce(String type) if (mail.equals(type) return new MailSender(); els

8、e if (sms.equals(type) return new SmsSender(); else System.out.println(请输入正确的类型!); return null; public class FactoryTest public static void main(String args) SendFactory factory = new SendFactory(); Sender sender = duce(sms); sender.Send(); 输出:this is sms sender!(2)多个工厂方法模式多个工厂方法模式对普通工厂方法

9、模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。关系图:将上面的代码做下修改,改动下SendFactory类就行,如下:public class SendFactory public Sender produceMail() return new MailSender(); public Sender produceSms() return new SmsSender(); public class FactoryTest public static void main(String args) SendFacto

10、ry factory = new SendFactory(); Sender sender = duceMail(); sender.Send(); 输出:this is mailsender!(3)静态)静态工厂方法模式工厂方法模式将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。public class SendFactory public static Sender produceMail() return new MailSender(); public static Sender produceSms() return new SmsSe

11、nder(); public class FactoryTest public static void main(String args) Sender sender = SendFduceMail(); sender.Send(); 应用实例: Spring BeanFactoryspring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。应用实例:Spring 工厂方法注入/* * 非静态的工厂方法注入 * author Administrator * */ p

12、ublic class CarFactory public Car createHongQiCar() Car car = new Car(); car.setName(红旗); car.setSpeed(200); return car; 对应的对应的bean.xml文件文件 /* * 静态的工厂方法注入 * author Administrator * */ public class CarFactory2 public static Car createHongQiCar() Car car = new Car(); car.setName(红旗); car.setSpeed(200);

13、 return car; 对应的对应的bean2.xml文件文件 问题工厂方法模式有一个问题:类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?3、抽象工厂模式(抽象工厂模式(Abstract Factory)抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码示例public interface Sender public void Send(); public class MailSender implements Sender Override publ

14、ic void Send() System.out.println(this is mailsender!); public class SmsSender implements Sender Override public void Send() System.out.println(this is sms sender!); 两个工厂类:public class SendMailFactory implements Provider Override public Sender produce() return new MailSender(); public class SendSmsF

15、actory implements Provider Override public Sender produce() return new SmsSender(); public interface Provider public Sender produce(); public class Test public static void main(String args) Provider provider = new SendMailFactory(); Sender sender = duce(); sender.Send(); 该模式的好处:如果你现在想增加一

16、个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!4、建造者模式(建造者模式(Builder)将各种产品集中起来进行管理,用来创建复合对象。复合对象就是指某个类具有不同的属性,其实建造者模式就是前面抽象工厂模式和最后的Test结合起来得到的public class Builder private List list = new ArrayList(); public void produceMailSender(int count) for(int i=0; icount; i+) li

17、st.add(new MailSender(); public void produceSmsSender(int count) for(int i=0; icount; i+) list.add(new SmsSender(); public class Test public static void main(String args) Builder builder = new Builder(); duceMailSender(10); 建造者模式将很多功能集成到一个类里,这个类可以创造出比较复杂的东西。与工厂模式的区别就是:工厂模式关注的是创建单个产品,而建造者模

18、式则关注创建符合对象,多个部分。建造者模式应用场景相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式,需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式是非常合适。应用实例:AltrtDialog.Builder在在android中的应用中的应用 对话框 Dialog:Dialog的建造过程就是一个典型的“建造者模式”,通过Builder来设置不同的参数,创建出不同的Dialog。 / 创建一个A

19、lertDialog对话框 Dialog dialog = new AlertDialog.Builder(this) .setTitle(登录提示) .setIcon(R.drawable.questionmark) .setMessage(是否登录?) .setPositiveButton(确定, this) .setNeutralButton(退出, this) .create(); dialog.show();5、原型模式(、原型模式(Prototype)模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。public interface Prototy

20、pe /* * 克隆自身的方法 * return 一个从自身克隆出来的对象 */ public Object clone();public class ConcretePrototype1 implements Prototype public Prototype clone() /最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了 Prototype prototype = new ConcretePrototype1(); return prototype; public class ConcretePrototype2 implements Prototype public Pr

21、ototype clone() /最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了 Prototype prototype = new ConcretePrototype2(); return prototype; public class Client /* * 持有需要使用的原型接口对象 */ private Prototype prototype; /* * 构造方法,传入需要使用的原型接口对象 */ public Client(Prototype prototype) totype = prototype; public void operation() /需

22、要创建原型接口的对象 Prototype copyPrototype = prototype.clone(); Java 浅复制 & 深复制http:/ 去年买了一个本本,另外给本本配了罗技G1光电套。坑爹的是,光电套的鼠标是USB接口,键盘是PS2接口,可我的本本却没有PS2接口啊。于是跑到市场,淘了一个转接器。于是乎,我抽象了这么几个类。1、PS2Port(PS2接口)。2、USBPort(USB接口)。3、PS2ToUSB(对象适配器),将PS2接口装换成USB接口。4、TestAdapter(测试类),客户端。/* * PS2接口,圆口 * author eason * */ publ

23、ic interface PS2Port public void workWithPS2(); /* * USB接口,U口 * author eason * */ public interface USBPort public void workWithUSB(); * * 对象适配器 * 将PS2接口装换成USB接口 * 所以此类类型是USB接口(implements USBPort) + 成员变量ps2Port * */ public class PS2ToUSB implements USBPort private PS2Port ps2Port; public PS2ToUSB(PS2

24、Port ps2Port) this.ps2Port = ps2Port; Override public void workWithUSB() ps2Port.workWithPS2(); public class TestAdapter public static void main(String args) /1.我现在有一个PS2接口 PS2Port ps2Port = new PS2Port() Override public void workWithPS2() System.out.println(PS2工作中); ; /2.但是我需要的是一个USB接口啊,对我(client)来

25、说,我只认识USB接口 /3.经过PS2ToUSB的转换,PS2接口变成了USB接口 USBPort ps2ToUsbPort = new PS2ToUSB(ps2Port); ps2ToUsbPort.workWithUSB(); 优点:优点:通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。复用了现存的类,解决了现存类和复用环境要求不一致的问题。将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。缺点

26、:缺点:对于对象适配器来说,更换适配器的实现过程比较复杂。适用场景系统需要使用现有的类,而这些类的接口不符合系统的接口。想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。两个类所做的事情相同或相似,但是具有不同接口的时候。旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但我们不希望手动更改原有类的时候。使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。实例2:Spring Aop在Spring的Aop中,使用的Advice(通知)来增强被代理类的功能。Spring实现

27、这一AOP功能的原理就使用代理模式(1、JDK动态代理。2、CGLib字节码生成技术代理。)对类进行方法级别的切面增强,即,生成被代理类的代理类,并在代理类的方法前,设置拦截器,通过执行拦截器重的内容增强了代理方法的功能,实现的面向切面编程。实例2:Spring AopAdapter类接口类接口:Targetpublic interface AdvisorAdapter boolean supportsAdvice(Advice advice); MethodInterceptor getInterceptor(Advisor advisor); MethodBeforeAdviceAdapt

28、er类类,Adapterclass MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable public boolean supportsAdvice(Advice advice) return (advice instanceof MethodBeforeAdvice); public MethodInterceptor getInterceptor(Advisor advisor) MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(

29、); return new MethodBeforeAdviceInterceptor(advice); 7、装饰器装饰器模式(模式(Decorator)装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。实例分析项目经理接到一个项目,项目最终要完成编码。项目经理接到项目后,先做些前期的工作(比如需求分析、设计),然后将编码工作委派给程序员,程序员干完后,项目经理做项目的收尾工作。代码实现:/* * 项目 */public interface Project /* *

30、 编码 */ void doCoding();/* * 程序员 */public class Employe implements Project public void doCoding() System.out.println(“程序员在编写代码,加班编啊编啊,终于编完了!); /* * 项目经理 */public class Manager implements Project private Project project; / 实际上存放的实际上存放的是程序员对象是程序员对象 public Manager(Project project) ject = project

31、; /* * 编码 */ public void doCoding() / 项目经理开始新的工作 startNewWork(); /* * 模板:定义项目经理自己的事情 */ public void startNewWork() / 项目经理在做早期工作 doEarlyWork(); / 项目经理很牛,做完需求和设计后,直接将编码委派给程序员干 project.doCoding(); / 项目经理在做收尾工作 doEndWork(); /* * 项目经理自己的事情:做早期工作 */ public void doEarlyWork() /* * 项目经理做收尾工作 */ public void

32、doEndWork() /* * 具体的项目经理A */public class ManagerA extends Manager public ManagerA(Project project) super(project); /* * 项目经理自己的事情:做早期工作 */ public void doEarlyWork() System.out.println(项目经理A 在做需求分析); System.out.println(项目经理A 在做架构设计); System.out.println(项目经理A 在做详细设计); /* * 具体的项目经理B */public class Mana

33、gerB extends Manager public ManagerB(Project project) super(project); /* * 项目经理自己的事情:做早期工作 */ public void doEarlyWork() System.out.println(项目经理B 在做需求分析); System.out.println(项目经理B 在做详细设计); /* * 项目经理做收尾工作 */ public void doEndWork() System.out.println(项目经理B 在做收尾工作); /* * 客户端测试 */ public class Client pu

34、blic static void main(String args) Project employe = new Employe(); /代码工人代码工人 Project managerA = new ManagerA(employe); /项目经理项目经理 Project managerB = new ManagerB(employe); /项目经理项目经理 /以经理的名义将编码完成,功劳都是经理的,实际编码的是工人 managerA.doCoding(); managerB.doCoding(); 运行结果:项目经理A 在做需求分析 项目经理A 在做架构设计 项目经理A 在做详细设计 代码工人 在编写代码,加班编啊编啊,终于编完了! 项目

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论