设计模式

boys 贡献于2013-12-15

作者 微软中国  创建于2011-08-20 02:25:00   修改者微软中国  修改于2012-02-09 04:57:00字数7522

文档摘要:设计模式是前辈总结的一些编程经验,在面向对象设计者经常遇到的一些问题,如避免重复设计,代码重用,可扩展性,可维护性提供了一些解决方案GoF模式(gangoffour)23种创建型设计模式AbstractFactory模式Builder模式FactoryMethod模式Prototype模式Singleton模式结构型设计模式Adapter模式Bridge模式Composite模式Decorator模式Facade模式Flyweight模式Proxy模式行为设计模式ChainofResponsibility模式Command模式Interpreter模式Iterator模式Mediator模式Memento模式Observer模式State模式Strategy模式TemplateMethod模式Visitor模式Singleton模式单例模式要点:单例类只可有一个实例.
关键词:

设计模式 设计模式是前辈总结的一些编程经验, 在面向对象设计者经常遇到的一些问题, 如避免重复设计,代码重用,可扩展性,可维护性 提供了一些解决方案 GoF模式(gang of four) 23 种 创建型设计模式 Abstract Factory模式 Builder模式 Factory Method模式 Prototype模式 Singleton模式 结构型设计模式 Adapter模式 Bridge模式 Composite模式 Decorator模式 Facade模式 Flyweight模式 Proxy模式 行为设计模式 Chain of Responsibility模式 Command模式 Interpreter模式 Iterator模式 Mediator模式 Memento模式 Observer模式 State模式 Strategy模式 Template Method模式 Visitor模式 Singleton模式 单例模式要点: 单例类只可有一个实例, 单例类不能让外界创建 即不能让外界new 单例类必须自己创建自己这惟一的实例 java中的单例 java.lang.Runtime java.awt.Toolkit 实现方式1 public class Singleton_1 { //静态私有自引用的成员变量 private static Singleton_1 singleton=null; //私有的构造方法 private Singleton_1 (){} // 静态工厂方法,返还此类的惟一实例 public static Singleton_1 newInstance(){ if(singleton==null){ System.out.println("创建对象"); singleton=new Singleton_1(); } return singleton; } } 实现方式2 /** * 静态初始化创建方式 */ public class Singleton_2 { private static Singleton_2 singleton=new Singleton_2(); private Singleton_2(){ System.out.println("实例化单例类"); } public static Singleton_2 newInstance(){ return singleton; } } 实现方式3 /** * * 多线程环境创建方式 * 对象实例由最先进入的那个线程创建, * 后来的线程在进入时(instence == null)为假, 不会再去创建对象实例了。 但是这种实现方式增加了额外的开销,损失了性能 */ public class Singleton_3 { private static Singleton_3 singleton=null; private Singleton_3(){} /* * 线程同步 处理多线程环境 */ /*synchronized public static Singleton_3 newInstance(){ if(singleton==null){ singleton=new Singleton_3(); } return singleton; }*/ /*或者*/ public static Singleton_3 newInstance(){ synchronized(Singleton_3.class){ if(singleton==null){ singleton=new Singleton_3(); } } return singleton; } } 简单工厂模式 由一个工厂类根据传入的参数,动态的决定应该创建出哪一个产品类的实例. 优点 工厂类是整个模式的关键.包含了必要的逻辑判断, 根据外界给定的信息,决定究竟应该创建哪个具体类的对象. 通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来, 仅仅需要负责“消费”对象就可以了. 而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利, 有利于整个软件体系结构的优化 缺点 1------由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则, 将全部创建逻辑集中到了一个工厂类中. 2------当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,对系统的维护和扩展不利 //抽象产品角色 public interface IFruit { public void show(); } //具体产品角色 public class 苹果 implements IFruit { public void show() { System.out.println("我是苹果"); } } //具体产品角色 public class 香蕉 implements IFruit { public void show() { System.out.println("我是香蕉"); } } //工厂角色 public class FruitFactory { public static IFruit create(String name){ IFruit fruit=null; if(name.equalsIgnoreCase("苹果")){ fruit=new 苹果(); } if(name.equalsIgnoreCase("香蕉")){ fruit=new 香蕉(); } return fruit; } } //测试类 public class Client { public static void main(String[] args) { IFruit fruit=FruitFactory.create("苹果"); fruit.show(); fruit=FruitFactory.create("香蕉"); fruit.show(); } } 工厂方法模式 定义一个用于创建对象的接口,让子类决定实例化哪一个类。 Factory Method 使一个类的实例化延迟到其工厂子类 解决了单个对象的创建问题 适用性 当一个工厂类无法预料要创建哪种类的对象 或是一个类需要由子类来指定创建的对象时 优点 在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将创建的工作交给子类去做。 这个核心类成为一个抽象工厂的角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类实例化的细节。这使得工厂方法模式可以允许系统在不修改具体工厂角色的情况下引进新的产品,使其具有超越简单工厂模式的优越性。在系统中加入新产品时,不需要对抽象工厂和抽象产品提供的接口进行修改,而只要添加一个具体工厂和具体产品就可以了 缺点 在添加新产品时,需要编写新的具体产品类, 而且还要提供与之对应的具体工厂类, 当两者都比较简单时,系统的额外开销相对也会较大 //抽象产品角色 public interface 水果 { public void show(); } //具体产品角色 public class 苹果 implements 水果 { public void show() { System.out.println("苹果"); } } //具体产品角色 public class 香蕉 implements 水果 { public void show() { System.out.println("香蕉"); } } //抽象工厂角色 public interface 水果工厂 { public 水果 produce(); } //具体工厂角色 public class 苹果工厂 implements 水果工厂 { //生产苹果 public 水果 produce() { System.out.println("创建苹果"); return new 苹果(); } } //具体工厂角色 public class 香蕉工厂 implements 水果工厂{ //制造香蕉 public 水果 produce() { System.out.println("创建香蕉"); return new 香蕉(); } } //客户代码 public class Client { public static void main(String[] args) { 水果工厂 mobileFactory=new 苹果工厂(); 水果 mobile=mobileFactory.produce(); mobile.show(); mobileFactory=new 香蕉工厂(); mobile=mobileFactory.produce(); mobile.show(); } } 抽象工厂模式 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 解决了一系列相关或相互依赖对象的创建问题 优点 1.隔离了具体类的生成,使得客户不需要知道什么被创建了.由于这种隔离,更换一个具体工厂就变得相对容易 2.实现了高内聚,低偶合的设计目的,因此被广泛应用 3.使用抽象工厂模式最大好处是, 当一个产品族中的多个对象被设计成一起工作时, 他能保证客户端始终只使用同一个产品族中的对象. 缺点 在添加新产品对象时,难以扩展抽象工厂以便生产新种类的产品, 这是因为抽象工厂接口规定了所有可能被创建的产品集合, 要支持新种类的产品就意味着要对该接口进行扩展, 而这将涉及到对抽象工厂及其所有子类的修改,显然有小小的不便, //抽象产品角色 public interface IFruit { public void fruitName(); } //具体产品角色 public class Orange implements IFruit { public void fruitName() { System.out.println("橙子"); } } //具体产品角色 public class Apple implements IFruit { public void fruitName() { System.out.println("苹果"); } } //抽象产品角色 public interface IAnimal { public void eat(IFruit fruit); } //具体产品角色 public class Tiger implements IAnimal { public void eat(IFruit fruit) { System.out.println("tiger eat "+fruit.getClass().getSimpleName()); } } //具体产品角色 public class Lion implements IAnimal { public void eat(IFruit fruit) { System.out.println("lion eat "+fruit.getClass().getSimpleName()); } } //抽象工厂角色 public interface IAbstractFactory { public IFruit createFruit(); public IAnimal createAnimal(); } //具体工厂角色A public class ConcreteFactoryA implements IAbstractFactory { public IAnimal createAnimal() { return new Lion(); } public IFruit createFruit() { return new Orange(); } } //具体工厂角色B public class ConcreteFactoryB implements IAbstractFactory { public IAnimal createAnimal() { return new Tiger(); } public IFruit createFruit() { return new Apple(); } } //客户中间联系类 public class Client { private IFruit fruit; private IAnimal animal; public Client(IAbstractFactory factory){ fruit=factory.createFruit(); animal=factory.createAnimal(); } public void run(){ animal.eat(fruit); } } //测试代码 public class Test { public static void main(String[] args) { IAbstractFactory factory=new ConcreteFactoryA(); Client client=new Client(factory); client.run(); factory=new ConcreteFactoryB(); client=new Client(factory); client.run(); } } Proxy模式 为目标对象提供一种代理以控制对这个对象的访问 从而添加新的功能 抽象角色:声明真实对象和代理对象的共同接口 真实对象:实现抽象角色中的方法 代理对象: 内部含有对真实对象的引用,从而可以操作真实对象, 同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。 同时,代理对象可以在执行真实对象操作时,附加其他的操作, 客户调用者 接口 目标对象 (真实对象) 代理对象(proxy) 静态代理 /** * 抽象角色:声明真实对象和代理对象的共同接口 */ public interface IHello { public void hello(String name); } /** * 真实角色,实现抽象角色中的方法 */ public class RealHello implements IHello { public void hello(String name) { System.out.println("Hello..... " + name); } } /** * 代理对象 */ public class HelloProxy implements IHello { // 对应的实体引用,使得代理对象可以访问实体 private IHello helloObject; public HelloProxy(IHello helloObject) { this.helloObject = helloObject; } public void hello(String name) { // 在请求之前 记录服务 preRequest("hello method starts...."); // 执行业务逻辑 helloObject.hello(name); // 在请求之后 记录服务 afterRequest(); } private void preRequest(String msg) { System.out.println("preRequest 方法执行在前"); } private void afterRequest(){ System.out.println("afterRequest方法执行在后"); } } /** *测试类 */ public class HelloDemo { public static void main(String[] args) { IHello myHello=new HelloProxy(new RealHello()); myHello.hello("梅超风"); } } JDK动态代理 CGLIB 可以代理实现任意接口的类,在运行时动态生成字节码 这样的类为动态代理类 目的:动态添加新功能 JDK动态代理主要涉及的类和接口: Proxy类 提供用于创建动态代理类和实例的静态方法 InvocationHandler 代理对象的处理程序实现的接口 目标对象要求:必须实现接口 //抽象角色 public interface IHello{ public void hello(String name); public void show(); } //真实对象,实现抽象角色中的方法 public class RealHello implements IHello { public void hello(String name) { System.out.println("Hello....." + name); } public void show(){ System.out.println("执行show()"); } } //代理对象的处理程序实现的接口实现类,用来给对象增加日志记录 public class LogHandler implements InvocationHandler { private Logger logger = Logger.getLogger(this.getClass().getName()); // 代理对应的实际对象 private T t; //返回代理对象 public Object bind(T t) { this.t = t; // 设置目标对象 /* Proxy类:动态代理类 使用代理工厂生成代理对象 返回代理类的一个实例,返回后的代理类可以当作被代理类使用 newProxyInstance()参数说明: 真实对象的classLoader是类装载器, interfaces是真实类所拥有的全部接口的数组 this 表示一个InvocationHandler对象 */ return Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), this); } // 截获对象的方法调用,提供一些前处理和后处理 //invoke() 参数说明:proxy 指代理对象,method是目标对象被代理的方法, args参数列表 public Object invoke(Object proxy, Method method, Object[] args){ Object result = null; try { System.out.println(proxy.getClass().getName()); preRequest(method.getName()+"开始调用"); result = method.invoke(t, args); afterRequest(method.getName()+"调用结束"); } catch (Exception e) { logger.error("日志记录失败"); } return result; } private void preRequest(String message) { logger.info(message); } private void afterRequest(String message) { logger.info(message); } } /** *测试类 */ public class HelloDemo { public static void main(String[] args) { LogHandler logHandler = new LogHandler(); IHello helloProxy = (IHello) logHandler.bind(new RealHello()); helloProxy.hello("梅超风"); helloProxy.show(); } }

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 6 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档