设计模式
来源:互联网 发布:西安行知中学是83中吗 编辑:程序博客网 时间:2024/06/03 21:51
更新ing
SOLID原则
设计模式
单例模式Singleton
定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
扩展:可以创建固定数量的对象。
本质
控制实例数目
优点
- 节约资源
缺点
- 单例是一个虚拟机范围的,因为类装载功能是虚拟机的。对于集群环境,单例模式不适用。
示例
懒汉式:时间换空间
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; }}
饿汉式:空间换时间
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance(){ return instance; }}
最佳方案
public enum Singleton { instance; public void operation() { // 操作 }}
实际应用场景
- 读取配置文件
- 缓存
抽象工厂Abstract Factory
定义
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
本质
选择产品簇的实现
优点
- 分离接口和实现
- 使得切换产品簇变得容易
缺点
- 不太容易扩展新的产品
- 容易造成类层次复杂
示例
- Abstract Factory:抽象工厂,定义创建一系列产品对象的操作接口
- Concrete Factory:具体的工厂,实现抽象工厂定义的方法,具体实现一系列产品对象的创建
- Abstract Product:定义一类产品对象的接口
- Concrete Product:具体的产品实现对象,通常在具体工厂里面,会选择具体的产品实现对象,来创建符合抽象工厂定义的方法返回的产品类型的对象
- Client:客户端,主要使用抽象工厂来获取一系列所需要的产品对象,然后面向这些产品对象的接口编程,以实现需要的功能。
抽象工厂接口
public interface AbstractFactory { public AbstractProductA createProductA(); public AbstractProductB createProductB();}
抽象产品A的接口
public interface AbstractProductA {}
抽象产品B的接口
public interface AbstractProductB {}
产品A具体实现
public class ProductA1 implements AbstractProductA {}public class ProductA2 implements AbstractProductA {}
产品B具体实现
public class ProductB1 implements AbstractProductB {}public class ProductB2 implements AbstractProductB {}
具体工厂实现
public class ConcreteFactory1 implements AbstractFactory { public AbstractProductA createProductA() { return new ProductA1(); } public AbstractProductB createProductB() { return new ProductB1(); }}public class ConcreteFactory2 implements AbstractFactory { public AbstractProductA createProductA() { return new ProductA2(); } public AbstractProductB createProductB() { return new ProductB2(); }}
客户端
public class Client { public static void main(String[] args) { AbstractFactory af = new ConcreteFactory1(); af.createProductA(); af.createProductB(); }}
实际应用场景
- 电脑组装,有不同厂家的cpu和不同厂家的主板等一系列产品。
DAO(Data Access Object)数据访问对象
- 数据源不同,例如:数据库数据源、LDAP数据源;本地数据源,远程数据源。
- 存储类型不同,关系型数据库、面向对象数据库、纯文件、XML
- 访问方式的不同,JDBC、JPA、EntityBean、Hibernate、iBatis
- 供应商不同,oracel,mysql
- 版本不同
DAO抽象和封装所有对数据的访问。
- 底层存储方式固定可以用工厂方法
- 底层存储方式不固定可以用抽象工厂模式
工厂方法Factory Methon
定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使用一个类的实例化延迟到其子类。
本质
延迟到子类来选择实现
优点
- 让父类不知道具体实现的情况下,完成自身的功能调用;而具体的实现延迟到子类来实现
- 更容易扩展对象的新版本,工厂方法给子类提供一个挂钩,使得扩展的对象版本变得非常容易
- 连接平行的类层次
缺点
- 具体产品对象和工厂方法的耦合性
示例
- Product:定义工厂方法所创建的对象的接口,也就是实际需要使用的对象的接口。
- ConcreteProduct:具体的Product接口的实现对象
- Creator:创建器,声明工厂方法,工厂方法通常会返回一个Product类型的实例对象,而且多是抽象方法。也可以在Creator里面提供工厂方法的默认实现,让工厂方法返回一个缺省的Product类型的实例对象。
- ConcreteCreator:具体的创建器对象,覆盖实现Creator定义的工厂方法,返回具体的Product实例。
Product
public interface Product { // 定义Product的属性和方法}
ConcreteProduct
public class ConcreteProduct implements Product { // 实现Product要求的方法}
创建器
public abstract class Creator { // 创建Product的工厂方法,一般不对外 protected abstract Product factoryMethod(); // 提供给外部使用的方法 public void someOperation() { Product product = factoryMethod(); }}
创建器具体实现
public class ConcreteCreator extends Creator { protected Product factoryMethod() { return new ConcreteProduct(); }}
实际应用场景
- 实现一个导出数据的应用框架,来让客户选择数据的导出方式,并真正执行数据导出。各分公司在局域网独立运行自己的服务,每天业务结束将数据导出成某种格式,传送给总部,总部导入数据,核算。
- 如果一个类需要创建某个接口的对象,但是又不知道具体的实现,这种情况可以选用工厂方法模式,把创建对象的工作延迟到子类中去实现
- 如果一个类本身就希望由它的子类来创建所需的对象的时候
IoC/DI
Q&A
- 参与者都有谁?
- 某个对象:任意的,普通的Java对象
- Ioc/DI容器:框架程序
- 某个对象的外部资源:对象需要的,但是从对象外部获取的,都统称为资源,比如对象需要的其他对象,或者是对象需要的文件资源等
- 依赖:谁依赖于谁?为什么需要依赖?
- 某个对象依赖于IoC/DI容器
- 对象需要IoC/DI的容器来提供对象需要的外部资源
- 注入:谁注入于谁?到底注入什么?
- Ioc/DI容器注入某个对象
- 注入某个对象所需要的外部资源
- 控制反转:谁控制谁?控制什么?为何叫反转(有反转就应该有正转了)?
- IoC/DI容器来控制对象
- 主要控制对象实例的创建
- 反转是相对正向而言的。如果A里面使用了C,当然会直接去创建C的对象,也就是说A主动去获取外部资源C,这叫正向。反向就是A不再主动去获取外部资源C,而是被动等待,等待Ioc/DI容器获取一个C的实例,然后反向注入到A类中。
- 依赖注入和控制反转是同一概念吗?
- 依赖注入和控制反转是对同一件事的不同描述。依赖注入(应用程序角度):应用程序依赖容器创建并注入它所需要的外部资源;控制反转(容器角度):容器控制应用程序,由容器反向地向应用程序注入其所需要的外部资源。
简单工厂Simple Factory
定义
提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口,抽象类也可以是具体类。
本质
选择实现
优点
- 帮助封装,让组件外部能真正面向接口编程
- 解耦,通过简单工厂,实现客户端和具体实现类解耦
缺点
- 使用时,必须对配置非常熟悉
- 静态方法创建接口,不方便扩展子工厂(通常也不需要扩展,所以不算一个严重的缺点)
示例
- Api:定义客户所需要的功能接口
- Impl:具体实现Api的实现类,可能会有多个
- Factory:工厂,选择合适的实现类来创建Api接口对象
- Client:客户端,通过Factory来获取Api接口对象,然后面向Api接口编程
API定义
/** * 接口定义 * /public interface Api { public void operation(String s);}
实现A
/** * 接口的具体实现A * /public class ImplA implements Api { public void operation(String s) { System.out.println("ImplA s==" + s); }}
实现B
/** * 接口的具体实现B * /public class ImplB implements Api { public void operation(String s) { System.out.println("ImplB s==" + s); }}
工厂类
public class Factory { public static Api createApi(int condition) { Api api = null; if(condition == 1) { api = new ImplA(); } else if(condition == 2) { api = new ImplB(); } return api; }}
配置版工厂类(反射,可考虑用NIO优化)
public class FactoryTest { public static Api createApi() { Properties p = new Properties(); InputStream in = null; try { in = FactoryTest.class.getResourceAsStream("FactoryTest.properties"); p.load(in); } catch (IOException e) { System.out.println(""); e.printStackTrace(); } finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } Api api = null; try { api = (Api) Class.forName(p.getProperty("implClass")).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return api; }}
客户端
public class Client { public static void main(String [] args) { Api api = Factory.createApi(1); api.operation("正在使用简单工厂"); }}
配置版客户端
public class Client { public static void main(String [] args) { Api api = Factory.createApi(); api.operation("正在使用简单工厂"); }}
实际应用场景
- 如果想要完全封装隔离具体实现,让外部只能通过接口来操作封装体
- 如果想要把创建对象的职责集中管理和控制
建造模式Builder
定义
将一个复杂的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
本质
分离整体构建算法和部件构造
优点
- 松散耦合
- 可以很容易地改变产品的内部表示。
- 更好的复用性,很好的实现了构建算法和具体产品实现的分离。
缺点
未总结
示例
- Builder:生成器接口,定义创建一个Product对象所需的各个部件的操作。
- ConcreteBuilder:具体的生成器实现,实现各个部件的创建,并负责组装Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法
- Director:指导者,主要用来使用Builder接口,以一个统一的过程来构建所需要的Product对象
- Product:产品,表示被生成器构建的复杂对象,包含多个部件
生成器接口
public interface Builder { public void buildPart();}
具体生成器的实现
public class ConcreteBuilder implements Builder { // 生成器最终构建的产品对象 private Product resultProduct; // 获取最终构建的产品对象 public Product getResult() { }s public void buildPart() { // 构建某个部件 }}
相应的产品对象接口
public interface Product {}
指导者
public class Director { // 持有当前需要使用的生成器对象 private Builder builder; public Director(Builder builder) { this.builder = builder; } // 指导生成器构建最终的产品对象 public void construct() { // 通过使用生成器接口来构建最终的产品对象 builder.buildPart(); }}
实际应用场景
- 一部分是部件构造和产品装配,另一部分是整体构建的算法
- 如果创建对象的算法,应该独立于该对象的组成部分以及它们的装配方式时
- 如果同一个构建过程有着不同的表示时
原型模式Prototype
定义
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象
本质
优点
缺点
示例
- Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求它们都要实现这里定义的克隆方法。
- ConcretePrototype:实现Prototype接口的类,这些类真正实现了克隆自身的功能。
- Client:使用原型客户端,首先要获取到原型实例对象,然后通过原型实例克隆自身来创建新的对象实例
原型接口
public interface Prototype { public Prototype clone();}
克隆具体实现
public class ConcretePrototype1 implements Prototype { private String field1; private Product product1; public String getProduct1() { return this.product1; } pubilc void setProduct1(String product1) { this.product1 = product1; } public String getField1() { return this.field1; } pubilc void setField1(String field1) { this.field1 = field1; } public Prototype clone() { Prototype prototype = new ConcretePrototype1(); prototype.setField1(this.field1); prototype.setProduct1((Product) this.product1.cloneProduct()); return prototype; }}public class ConcretePrototype2 implements Prototype { private String field2; private Product product2; public String getProduct2() { return this.product2; } pubilc void setProduct2(String product2) { this.product2 = product2; } public String getField2() { return this.field2; } pubilc void setField2(String field2) { this.field2 = field2; } public Prototype clone() { Prototype prototype = new ConcretePrototype2(); prototype.setField1(this.field2); prototype.setProduct2((Product) this.product2.cloneProduct()); return prototype; }}
原型管理器
public class PrototypeManager { private static Map<String, Prototype> map = new HashMap<String, Prototype>(); private PrototypeManager() { } public synchronized static void setPrototype(String prototypeId, Prototype prototype) { map.put(prototypeId, prototype); } public synchronized static void removePrototype(String prototypeId) { map.remove(prototypeId); } public synchronized static Prototype getPrototype(String prototypeId) throws Exception { Prototype prototype = map.get(prototypeId); if(prototype == null) { throw new Exception("您希望获取的原型还没有注册或已被销毁"); } return prototype; }}
客户端
public class Client { private Prototype prototype; public Client(Prototype prototype) { this.prototype = prototype; } public void operation() { Prototype newPrototype = prototype.clone(); }}
实际应用场景
观察者模式Observer
定义
对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自动更新。
本质
触发联动
优点
- 观察者模式实现了观察者和目标之间的抽象耦合
- 观察者模式实现了动态联动
- 观察者模式支持广播通信
缺点
- 可能会引起无谓的操作
示例
- Subject:目标对象,通常具有如下功能
- 一个目标可以被多个观察者观察
- 目标提供对观察者注册和退订的维护
- 当目标的状态发生变化时,目标负责通知所有注册的,有效的观察者
- Observer:定义观察者的接口,提供目标通知时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,以获取目标对象的数据
- ConcreteSubject:具体的目标实现对象,用来维护目标状态,当目标对象的状态发生变化,通知所有注册的,有效的观察者,让观察者执行相应的处理。
- ConcreteObserver:观察者的具体实现对象,用来接收目标的通知,并进行相应的后续处理,比如更新自身的状态以保持和目标的相应状态一致。
目标对象
public class Subject { private List<Observer> observers = new ArrayList<Observer>(); // 注册观察者对象 public void attach(Observer observer) { observers.add(observer); } // 删除观察者对象 public void detach(Observer observer) { observers.remove(observer); } // 通知所有注册的观察者对象 protected void notifyObservers() { for(Observer observer: observers) { observer.update(this); } }}
具体的目标对象
public class ConcreteSubject extends Subject { private String subjectState; public String getSubjectState() { return subjectState; } public void setSubjectState(String sunjectState) { this.subjectState = subjectState; this.notifyObservers(); }}
观察者接口
public interface Observer { public void update(Subject subject);}
具体观察者
public class ConcreteObserver implements Observer { private String observerState; public void update(Subject subject) { observerState = ((ConcreteSubject) subject).getSubjectState(); }}
客户端
public class Client { public static void main(String[] args) { NewsPaper subject = new NewsPaper(); Reader reader1 = new Reader(); reader1.setName("张三"); Reader reader2 = new Reader(); reader2.setName("李四"); Reader reader3 = new Reader(); reader3.setName("李四"); subject.attach(reader1); subject.attach(reader2); subject.attach(reader3); subject.setContent("本期内容是观察者模式"); }}
实际应用场景
- 推模式:目标对象主动向观察者推送目标的详细信息,不管观察者是否需要,推送的消息通常是目标对象的全部或部分数据,相当于是在广播通信。适用于目标对象知道观察者需要什么数据。
- 拉模式:目标对象在通知观察者的时候,只传递少量信息。如果观察者需要具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。适用于目标对象不知道观察者需要什么数据,将自己的引用传给观察者,让观察者按需取值。这个更加通用。
策略模式Strategy
定义
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
本质
分离算法,选择实现
优点
- 定义一系列算法
- 避免多重条件语句
- 更好的扩展性
缺点
- 客户必须了解每种策略的不同
- 增加了对象数目
- 只合适扁平的算法结构
示例
- Strategy:策略接口,用来约束一系列具体的策略算法。Context使用这个接口来调用具体的策略实现定义的算法
- ConcreteStrategy:具体的策略实现,也就是具体的算法实现
- Context:上下文,负责和具体的策略类交互。通常上下文会持有一个真正的策略实现,上下文还可以让具体的策略类来获取上下文的数据,甚至让具体的策略类来回调上下文的方法。
策略接口
public interface Strategy { public void algorithmInterface();}
具体策略
public interface ConcreteStrategyA implements Strategy { public void algorithmInterface() { }}public interface ConcreteStrategyB implements Strategy { public void algorithmInterface() { }}
上下文
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void contextInterface() { strategy.algorithmInterface(); }}
实际应用场景
责任链模式China of Responsibility
定义
使用多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到一个对象处理它为止。
本质
分离职责,动态组合
优点
- 请求者和接收者松散耦合
- 动态组合职责
缺点
- 产生很多细粒度对象
- 不一定能被处理。传递完都没被处理,需要提供默认的处理。
示例
- Handler:定义职责的接口
- ConcreteHandler:实现职责的类。在这个类中,实现对在它职责范围内请求的处理,如果不处理,就继续转发请求给后继者。
- Client:职责链客户端
职责的接口
public abstract class Handler { protected Handler successor; public void setSuccessor(Handler successor) { this.successor = successor; } public abstract void handleRequest();}
通用的请求对象
public class RequestModel { private String type; public RequestModel(String type) { this.type = type; } public String getType() { return type; }}
具体的请求对象
public class ConcreteRequestModel extends RequestModel { public final static String A_TYPE = "A"; public ConcreteRequestModel() { super(A_TYPE); } private String field1; ...}
具体的职责对象
public class ConcreteHandler1 extends Handler { public Object handleRequest(RequestModel rm) { // 根据某些条件判断是否属于自己处理的职责范围 boolean someCondition = false; Object result; if(someCondition) { // 处理 return result; } else { // 不处理,转发请求给后继职责对象 if(this.successor != null) { return this.successor.handleRequest(rm); } else { return result; } } }}
客户端(可采用链表改进客户端)
public class Client { public static void main(String[] args) { Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); h1.setSuccessor(h2); h1.handleRequest(); }}
实际应用场景
- 权限检查
- 通用数据校验
- 数据逻辑校验
- 过滤器
- 可以和组合模式一起使用,通过组合模式将责任组合起来
中介者模式Mediator
定义
本质
封装隔离
优点
- 松散耦合
- 集中控制交互
- 多对多变成一对多
缺点
- 过度集中化。中介者对象十分复杂,难于管理和维护。
示例
- Mediator:中介者接口,在里面定义各个同事之间交互需要的方法,可以是公共的通信方法,比如changed方法,大家都用,也可以是小范围的交互方法。
- ConcreteMediator:具体中介者实现对象。它需要了解并维护各个同事对象,并负责具体的协调各同事对象的交互关系。
- Colleague:同事类的定义,通常实现成抽象类,主要负责约束同事对象的类型,并实现一些具体同事类之间的公共功能。
- ConcreteColleague:具体的同事类,实现自己的业务,在需要与其他同事通信的时候,就与持有的中介者通信,中介者会负责与其他的同事交互。
同事类的抽象父类
public abstract class Colleague { private Mediator mediator; public Colleague(Mediator mediator) { this.mediator = mediator; } public Mediator getMediator() { return mediator; }}
同事类A
public class ConcreteColleagueA extends Colleague { public ConcreteColleagueA(Mediator mediator) { super(mediator); } public void someOperation() { // 需要跟其他同事通信的时候,通知中介者对象 getMediator().changed(this); }}
同事类B
public class ConcreteColleagueB extends Colleague { public ConcreteColleagueB(Mediator mediator) { super(mediator); } public void someOperation() { // 需要跟其他同事通信的时候,通知中介者对象 getMediator().changed(this); }}
中介者接口
public interface Mediator {
public void changed(Colleague colleague);}
中介者实现
public class ConcreateMediator implements Mediator { private ConcreteColleagueA colleagueA; private ConcreteColleagueB colleagueB; public void setConcreteColleagueA(ConcreteColleagueA colleague) { colleagueA = colleague; } public void setConcreteColleagueB(ConcreteColleagueB colleague) { colleagueB = colleague; } public void changed(Colleague colleague) { // 某个同事类发生了变化,通常需要与其他同事交互 // 具体协调相应的同事对象来实现协作行为 }}
客户端
public class Client {}
实际应用场景
- 如果一组对象之间的通信方式比较复杂,导致相互依赖,结构混乱,可以采用中介者模式
- 如果一个对象引用很多的对象,并直接跟这些对象交互,导致难以复用该对象
外观模式Facade
定义
为子系统中的一组接口提供一个一致的界面,也就是一个高层接口。
本质
为多模块提供统一接口,封装交互,简化调用
优点
- 减少外部与子系统内多模块的交互,松散耦合
- 出现变化时,只需修改Facade的实现就好,只需改这一个地方,由于很多客户端都会用这个外观模式,无需修改所有的客户端。从而达到一改全改。
- 调用多个模块在外观模式调用一次就好了,无需所有客户端都调用一次,减少重复调用
- 客户端无需了解系统的内部实现,无需了解每个模块的细节,也不需要去和多个模块交互,节省了学习成本。
- 将外部接口和外部接口分开。封装更好
缺点
- 过多或者不合理的Facade容易让人迷惑,到底是调用Facade好,还是直接调用模块好。
示例
A模块Api
public interface AModuleApi { public void testA1(); //系统外部使用 public void testA2(); //系统内部使用 public void testA3(); //系统内部使用}
实现A模块
public class AModuleImpl implements AModuleApi { public void testA1() { System.out.println("现在在A模块里面操作testA1方法"); } public void testA2() { System.out.println("现在在A模块里面操作testA2方法"); } public void testA3() { System.out.println("现在在A模块里面操作testA3方法"); }}
B模块Api
public interface BModuleApi { public void testB1(); //系统外部使用 public void testB2(); //系统内部使用 public void testB3(); //系统内部使用}
实现B模块
public class BModuleImpl implements BModuleApi { public void testB1() { System.out.println("现在在B模块里面操作testB1方法"); } public void testB2() { System.out.println("现在在B模块里面操作testB2方法"); } public void testB3() { System.out.println("现在在B模块里面操作testB3方法"); }}
C模块Api
public interface CModuleApi { public void testC1(); //系统外部使用 public void testC2(); //系统内部使用 public void testC3(); //系统内部使用}
实现B模块
public class CModuleImpl implements CModuleApi { public void testC1() { System.out.println("现在在C模块里面操作testC1方法"); } public void testC2() { System.out.println("现在在C模块里面操作testC2方法"); } public void testC3() { System.out.println("现在在C模块里面操作testC3方法"); }}
外观接口
public interface FacadeApi { // 只暴露对外部调用的接口 public void testA1(); public void testB1(); public void testC1(); public void test();}
外观类
public class Facade { public void test() { AModuleApi a = new AModuleImpl(); a.testA1(); BModuleApi b = new BModuleApi(); b.testB1(); CModuleApi c = new CModuleImpl(); c.testC1(); }}
客户端
public class Client { public static void main(String [] args) { Facade facade = new Facade(); facade.test(); }}
实际应用场景
代理模式Proxy
定义
为其他对象提供一种代理以控制对这个对象的访问。
本质
控制对象访问
优点
缺点
示例
- Proxy:代理对象。实现与具体的目标对象一样的接口,这样就可以使用代理来代替具体的目标对象。保存一个指向具体目标对象的引用,可以在需要的时候调用具体的目标对象。可以控制对具体目标对象的访问,并可以负责创建和删除它。
- Subject:目标接口,定义代理和具体目标对象的接口,这样就可以在任何使用具体目标对象的地方使用代理对象。
- RealSubject:具体的目标对象,真正实现目标接口要求的功能。
抽象的目标接口
public interface Subject { public void request();}
具体的目标对象,是真正被代理的对象
public class RealSubject implements Subject { public void request() { }}
代理对象的实现示意
public class Proxy implements Subject { private RealSubject realSubject = null; public Proxy(RealSubject realSubject) { this.realSubject = realSubject; } public void request() { // 在转调具体的目标对象前,可以执行一些功能处理 // 转调具体的目标对象的方法 realSubject.requst(); // 在转调具体的目标对象后,可以执行一些功能处理 }}
实际应用场景
- 一次性访问多条数据。当选择一个部门或者分公司时,要把这个部门或者分公司下的所有员工都显示出来,而且不要翻页,方便进行业务处理。
定义用户数据对象
public interface UserModelApi { public String getUserId(); public void setUserId(String userId); public String getName(); public void setName(String name); public String getDepId(); public void setDepId(String depId); public void String getSex(); public void setSex(String sex);}
代理类
public class Proxy implements UserModelApi { private UserModel realSubject = null; public Proxy(UserModel realSubject){ this.realSubject = realSubject; } // 标识是否已经重新装载过数据 private boolean loaded = false; public String getUserId() { return realSubject.getUserId(); } public void setUserId(String userId) { realSubject.setUserId(userId); } public String getName() { return realSubject.getName(); } public void setName(String name) { realSubject.setName(name); } public void setDepId(String depId) { realSubject.setDepId(depId); } public void setSex(String sex) { realSubject.setSex(sex); } public String getDepId() { // 需要判读是否已经装载过了 if(!this.loaded) { reload(); // 设置重新装载的标志为true this.loaded = true; } return realSubject.getDepId(); } public String getSex() { // 需要判读是否已经装载过了 if(!this.loaded) { reload(); // 设置重新装载的标志为true this.loaded = true; } return realSubject.getSex(); } private void reload() { Connection conn = null; try { conn = this.getConnection(); String sql = "select * from tbl_user where userId = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, realSubject.getUserId()); if(re.next()) { realSubject.setDepId(rs.getString("depId")); realSubject.setSex(rs.getString("sex")); } rs.close(); pstmt.close(); } catch (Exception err) { err.printStackTrace(); } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }}
- 动态代理AOP
代理分类
- 虚代理:根据需要来创建开销很大的对象,该对象只有在需要的时候才会被真正创建
- 远程代理:用来在不同的地址空间上代表同一个对象,这个不同的地址空间可以是在本机,也可以在其他机器上。在Java里面最典型的就是RMI技术
- copy-on-write代理:在客户端操作的时候,只有对象确实改变了,才会真的拷贝或者克隆一个目标对象,算是虚代理的一个分支
- 保护代理:控制对原始对象的访问,如果有需要,可以给不同的用户提供不同的访问权限,以控制他们对原始对象的访问。
- Cache代理:为那些昂贵操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果
- 防火墙代理:保护对象不被恶意用户访问和操作。
- 同步代理:使多个用户能够同时访问,目标对象而没有冲突。
- 智能指引:在访问对象时执行一些附加操作,比如,对指向实际对象的引用计数、第一次引用一个持久对象时,将它装入内存等。
适配器模式Adapter
定义
把不兼容的接口转换匹配成客户需要的接口,复用已有的功能
本质
转换匹配,复用功能。
优点
- 兼容老接口,更好的复用。
- 更好的扩展
缺点
- 过多使用适配器,会让系统非常零乱,不容易整体进行把握。
示例
- Client:客户端,调用自己需要的领域接口Target
- Traget:定义客户端需要的跟特定领域相关的接口
- Adaptee:已经存在的接口,通常能满足客户端的功能要求,但是接口与客户端要求的特定领域接口不一致,需要被适配
- Adapter:适配器,把Adaptee适配成为Client需要的Target
Target Api
public interface Target { public void request();}
被适配的类
public class Adaptee { public void specificRequest() { //具体功能 }}
适配器
public class Adapter implements Target { private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } public void request() { }}
客户端
public class Client { public static void main(String [] args) { Adaptee adaptee = new Adaptee(); Target target = new Adapter(adaptee); target.request(); }}
实际应用场景
- 如果想要使用一个已经存在的类,但是它的接口不符合你的需求
- 如果想创建一个可以复用的类,这个类可能和一些不兼容的类一起工作
- 如果想使用一些已经存在的子类,但是不可能对每一个子类都进行适配,这种情况可以选用对象适配器,直接适配这些子类的父类就可以了
装饰模式Decrator
定义
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。
本质
动态组合
优点
- 比继承更灵活。继承是静态的,装饰器采用把功能分离到每个装饰器中,通过对象组合动态使用。
- 更容易复用功能。
- 简化高层定义。
缺点
- 会产生很多细粒度的对象
示例
- Component:组件对象的接口,可以给这些对象动态地添加职责
- ConcreteComponent:具体的组件对象,实现组件对象接口,通常就是被装饰器装饰的原始对象,也就是可以给这个对象添加职责。
- Decorator:所有装饰器的抽象父类,需要定义一个与组件接口一致的接口,并持有一个Component对象,其实就是持有一个被装饰的对象。
- ConcreteDecorator:实际的装饰器对象,实现具体要向被装饰对象添加的功能
组件对象的接口
public abstract class Component { public abstract void operation();}
具体实现组件对象
public class ConcreteComponent extends Component { public void operation() { }}
装饰器的抽象父类
public abstract class Decorator extends Component { protected Component component; public Decorator(Component component) { this.component = component; } public void operation() { // 转发请求给组件对象,可以在转发前后执行一些附加动作 component.operation(); }}
装饰器的具体实现A
public class ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component component) { super(component); } // 添加的状态 private String addedState; public String getAddedState() { return addedState; } public void setAddedState(String addedState) { this.addedState = addedState; } public void operation() { // 调用父类的方法,可以在调用前后执行一些附加动作 super.operation(); // ... String useAddedState = addedState; }}
装饰器的具体实现B
public class ConcreteDecoratorB extends Decorator { public ConcreteDecoratorB(Component component) { super(component); } // 添加的职责 private void addedBehavior() { // 需要添加的职责实现 } public void operation() { // 调用父类的方法,可以在调用前后执行一些附加动作 super.operation(); // ... addedBehavior(); }}
实际应用场景
- 灵活的奖金计算
- I/O流
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式~~~~~~~~~~
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- 设计模式
- xdoj 1188: 大大数星星
- POJ3107Godfather找重心
- 卡尔曼滤波简介+ 算法实现代码
- Python中@property
- 集合框架-集合的嵌套遍历(多层嵌套)
- 设计模式
- 重新理解public static void main(String[] args) {}
- xdoj 1154: Nhywieza 的串
- "GIS讲堂"第七课内容公布
- 初学web前端-20170427
- [安卓基础]学习第三天
- k-近邻
- 使用mave开发mapreduce
- xdoj 1151: 万神的方程