Java常见设计模式应用场景
1、抽象工厂
应用场景:封装变化点。创建一系列相互依赖的对象。
在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时由于需求的变化,往往存在更多系列对象的创建工作。如何应对这各变化如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合。
public abstract Class AbstractFactory{
//创建一系列相互关联的对象如游戏场景中相互关联的Road,Building,Tunnel,Jungle对象
public abstract ProductA createProductA();
public abstract ProductB createProductB();
/........
}
//多系列体现在ConcreteFactoryA,ConcreteFactoryB这些具体工厂创建该系列下的多个相互关联的对象
public class ConcreteFactoryA extends AbstractFactory{
//具体创建ProductA,ProductB的哪个子类再这里指定,如
//这里相互关联的对象体现在ProductA1和ProductB1够成第一种风格
public ProductA createProductA(){
return new ProductA1();
return new ProductB1();
}
}
public class ConcreteFactoryB extends AbstractFactory{
//具体创建ProductA,ProductB的哪个子类再这里指定,如
public ProductA createProductA(){
return new ProductA2();
return new ProductB2();
}
}
public abstract class ProductA{
//其子类是ProductA1,ProductA2
//定义一些接口;
public void someMethod();
//......
}
public abstarct class ProductB{
//其子类是ProductB1,ProductB2
//定义一些接口;
public void someMethod();
//......
}
public class Test{
ProductA a;
ProductB b;
public static void main(String[] args){
//客户端要创建不同风格的游戏场景(多系列)
AbstractFactory factory = new ConcreteFactoryA();
ProductA a = factory.createProductA();
ProductB b = factory.createProductB();
play();
//创建另一种风格的游戏场景,只须更改ConcreteFactoryB();
//
//AbstractFactory factory = new ConcreteFactoryA();
//ProductA a = factory.createProductA();
//ProductB b = factory.createProductB();
//play();
}
public static void play(){
a.someMethod();
b.someMethod();
}
}
2、Builder
在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
Builder设计模式是应对这样的需求变化:如何提供一种“封装机制”来隔离“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”,不随着需求改变而改变。
//抽象定义如何构建Product及其子对象
public abstract class Builder{
//获取整体对象
public abstract Product getProduct();
//构建部分对象
public abstract void buildProductA();
public abstract void buildProductB();
public abstract void buildProductC();
}
//具体构建Product对象
public class ConcreteBuilder extends Builder{
//复杂对象是由其他子对象组合而成,Houser是由ProductA,productB,productC的一个或者多个实例组合而成
private Product product;
private List
productAList = new ArrayList();
private List
productBList = new ArrayList();
private List
productCList = new ArrayList();
//返回该复杂对象
public Product getProduct(){
product.setProductAList(this.productAList);
product.setProductBList(this.productBList);
product.setProductCList(this.productCList);
return this.product;
}
//构建ProductA
public void buildeProductA(){
this.productAList.add(new ProductAA());
//this.productAList.add(new ProductAB());
}
//构建ProductB
public void buildeProductB(){
this.productBList.add(new ProductBA());
//this.productBList.add(new ProductBB());
}
//构建ProductC
public void buildeProductC(){
this.productCList.add(new ProductCA());
//this.productCList.add(new ProductCB());
}
}
//复杂对象是由其他子对象组合而成,包含ProductA,ProductB,ProductC的实例
public abstract class Product{
private List ProductAList;
private List productBList;
private List productCList;
//...........
}
public class Test{
//定义构建Product的稳定的算法,如构建1个ProductA,两个ProductB,三个ProductC
//这个复杂对象面临剧烈的变化是指ProductA有子类ProductAA,ProductAB;ProductB有
//子类ProductBA,ProductBB;ProductC有子类ProductCA,ProductCB,这些具体子类的构建
//封装在具体的ConcreteBuilder里,客户端只须修改ConcreteBuilder即可
public static Product createProduct(Builder builder){
//如第一步创建1个ProductA
builder.createProductA();
//第二步两个ProductB
builder.createProductB();
builder.createProductB();
//第三步创建三个ProductC
builder.createProductC();
builder.createProductC();
builder.createProductC();
//最终才能获得Product对象
return builder.getProduct();
}
public static void main(String[] args){
Builder builder = new ConcreteBuilder();
Product product = this.createProduct(builder);
}
}
3、工厂方法(把变和不变的地方隔离出来)
紧耦合和松耦合:如何进行模块划分?
主模块(抽象部分)-->次模块(细节具体部分) 对模块进行分析(高层模块-->低层模块)
在软件系统中,经常面临着“某个对象”的创建工作;由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口。
如何应对这种变化?如何提供一种“封装机制”来隔离出“这种易变对象”的变化,从而保持系统中
“其他依赖该对象的对象(主逻辑)”不随着需求改变而改变?
解决:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟。
public abstract Class Car{
//定义一系列稳定的接口
}
public Class BMW extends Car{
//override car's method
}
public abstract Class AbstractFactory{
//只依赖于抽象Car,具体的Car延迟到具体的工厂中创建
public Car createCar();
}
public Class BMWFactory{
@override
public Car createCar(){
return new BMW();
}
}
public Class Test{
//客户端程序只依赖抽象的Car和抽象的AbstractFactory
//如果系统扩展其他车,只须修改这处的代码 = new BMWFactory();(当然可以放到配置文件中读取出来就不用改代码了)
//另外加两个类public Class KaiYue extends Car,public Class KaiYueFactory extends AbstractFactory
AbstractFactory factory = new BMWFactory();
Car car = factory.createCar();
}
4、Bridge模式
适用场景:将抽象部分与实现部分分离,使他们都可以独立地变化将
或将一个事物的多个维度的变化分离,该模式证明聚合比继承好
//最初的做法是将两个维度的抽象方法都集中在Abstraction中
//两个维度扩展出的所有子类都继承Abstraction,冗余太多
public abstraction class Abstraction{
public absracte void operate();
public absracte void operationImpl();
}
public class ConcreteAbstractionA extends Abstraction{
public void operate(){ };
public void operationImpl(){ };
}
public class ConcreteAbstractionB extends Abstraction{
public void operate(){ };
public void operationImpl(){ };
}
public class ConcreteAbstractionConcreteImplementorA extends ConcreteAbstractionA{
public void operate(){ };
public void operationImpl(){ };
}
public class ConcreteAbstractionConcreteImplementorB extends ConcreteAbstractionA{
public absracte void operate(){ };
public absracte void operationImpl(){ };
}
//............
//如果在多个维度上扩展,子类越来越多,实现代码有重复
改进后的代码
public abstract class Abstraction{
protected Implemetor implementor;
publlic Abstractor(Implementor implementor){
this.implementor = implementor;
}
//定义一些其他抽象方法
public abstract void operation();
}
public class ConcreteAbstraction extends Abstraction{
public ConcreteAbstraction(Implementor implementor){
super(implementor);
}
public void operation(){ };
}
public abstract Implementor{
public abstract void operationImpl();
}
public class ConcreteImplementorA extends Implementor{
}
public class ConcreteImplementorB extends Implementor{
}
public class Test{
public static void main(String[] args){
Implementor implemetor = new ConcreteImplementorA();
Abstraction abstraction = new ConcreteAbstraction(implementor);
abstraction.operation();
implementor.operationImpl();
}
}
5、适配器Adapter
在软件系统中,由于应用 环境的变化,常常要将"一些现在的对象"放到新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的
适用场景:在不改变原来实现的基础上,将原来不兼容的接口转换为兼容的接口。将一个类的接口转换至客户希望的另一个接口。Adapter
模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
//新环境所使用的接口,或者说是客户端想使用的接口
public abstract Target{
public void request();
}
//已经存在的specificRequest接口
public class Adaptee{
public void specificRequest(){ }
}
public class Adapter extends Target{
private Adaptee adaptee;
public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
public void request(){
//处理其它事项
//适配到目标接口
adaptee.specificRequest();
//处理其它事项
}
}
public class Client{
public static void main(String[] args){
Adapter adapter = new Adapter(new Adaptee());
adapter.request();
}
}
6、Decarator
过度地使用了继承来扩展对象的功能,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性
并且随着子类的增多,各子类的组合会导致更多子类的膨胀.动态地给一个对象增加一些额外的职责
public abstract class Component{
//定义一些抽象方法
public abstract void operation();
}
public abstract class ConcreteComponent{
public abstract void operation(){
//............原有功能
}
}
public abstract class Decorator{
private Component component;
private Decorator(Component component){
this.component = component;
}
//原有operation的功能
public void operation(){
this.component.operation();
}
}
//一个具体的Decorator就是扩展了Component类的operation();
//如果在Component类中添加一个行为则需要用Visitor模式,定义一个预留的待扩充的接口,很类似
public ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Decorator decorator){
super(decorator);
}
}
public ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Decorator decorator){
super(decorator);
}
public void operation(){
//扩展operation的功能
// Do some extension
otherMethod1();
operation();
}
}
public class Test{
public static void main(String[] args){
Component component = new ConcreteComponent();
Decorator decorator1 = new ConcreteDecoratorA();
Decorator decorator2 = new ConcreteDecoratorB();
}
public void operation(){
//扩展operation的功能
otherMethod2();
operation();
}
}
7、Command命令模式
对发送者和接收者完全解耦
public abstract class Sender{
private Command command;
public Sender(Command command){
this.command = command;
}
//发送命令
public abstract send(Command command);
}
//命令调度者,发送什么样的命令以及通告谁执行命令
public class CommandInvoker{
private Command commandA;
private Command commandB;
private Command commandC;
public CommandInvoker(Command commandA,Command commandB,Command commandC){
this.commandA = commandA;
this.commandB = commandB;
this.commandC = commandC;
}
//这里已经确定命令是发给谁执行的,以及系统中只有三个命令CommandA,CommandB,CommandC
//如果再加一个CommandD命令,command命令模式已无能为力,这里应该采用Visitor模式,如何将两者结合起来
public void executeCommandA(){
commandA.execute();
}
public void executeCommandB(){
commandB.execute();
}
}
public Interface Command{
public void execute();
}
public class CommandA implements Command{
private Receiver receiver;
public CommandA(Receiver receiver){
this.receiver = receiver;
}
public void execute(){
//真正的命令执行者是Receiver
receiver.execute();
}
}
public class CommandB implements Command{
private Receiver receiver;
public CommandB(Receiver receiver){
this.receiver = receiver;
}
public void execute(){
//真正的命令执行者是Receiver
receiver.execute();
}
}
//命令接收者
public class Receiver{
public void executeCommandA(){
//.......
}
public void executeCommandB(){
//.......
}
}
public class Test{
public static void main(String[] args){
//客户端只须定义一个命令,交给手下CommandInvoker去执行就行了
//至于具体的命令通知谁做什么事以及怎么执行不关注
CommandA commandA = new CommandA();
CommandB commandB = new CommandB();
CommandC commandC = new CommandC();
CommandInvoker invoker = new CommandInvoker(commandA,commandB,commandC);
commandA.execute();
commandB.execute();
commandC.exceute();
//问题,为什么非要执行三个命令呢?只执行一个命令我也要new CommandA,CommandB,CommandC
//最初的Comand是这样的
/**
public class Command{
public void executeCommandA(){};
public void executeCommandB(){};
}
//客户端程序,请求者和耦合度高,command模式将一个请求封装为一个对象:将每一个executeCommandA()封装成CommandA
//从而使你可用不同的请求对客户(行为的请求者)进行参数化:CommandInvoker invoker = new CommandInvoker(commandA,commandB,commandC);
Command comand = new Command();
command.executeCommandA();
command.executeCommandB();
*/
}
}
8、Visitor模式
场景是:在类层次结构稳定,而操作却面临频繁的变动
解决的问题是:在类层次结构的父类中要添加新的行为,这里所有的子类不得不跟着改动
解决方法是:只须添加一个Visitor就可以将所有子类的必须实现的方法集中到Visitor类中
public interface P{
//系统已有的方法
public void someMethod();
//预留的防止系统需要添加的新行为
public void accept(Visitor visitor);
}
public class PA implements P{
public void someMethod{
}
public void accep(Visitor visitor){
//把自己传进来PA类型
//这里使用了double dispatch 1:visitor的多态;2:this的转换(但是在静态编译过程中已经确定了)
visitor.run(this);
}
}
public class PB implements P{
//把自己传进来PB类型
visitor.run(this);
}
public class PC implements P{
//把自己传进来PC类型
visitor.run(this);
}
public abstract class Visitor{
//对应于三个子类要重写的子类方法
public abstract void run(PA pa);
public abstract void run(PB pb);
publilc abstract void run(PC pc);
}
public class MyVisitor extends Visitor{
public abstract void run(PA pa){
//具体PA子类的实现,复写的逻辑代码
//..........
}
public abstract void run(PB pb){
//具体PB子类的实现,复写的逻辑代码
//..........
}
publilc abstract void run(PC pc);{
//具体PC子类的实现,复写的逻辑代码
//..........
}
}
//ArrayList list = new ArrayList();
list.add(new PA());
list.add(new PB());
list.add(new PC());
Visitor vistor = new Visitor();
Iterator it = new Iterator();
while(it.hasNext()){
P p = (P) it.next();
p.accept(visitor);
}
9、Strategy模式
某些对象使用的算法可能多种多样经常改变
策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
如
public class Calculator{
public String calculate(float a,float b,String type){
//变化点1 type; 2processA();
if(type.equals "A"){
processA();
}else if(type.equals "B"){
processB();
}else if(type.equals "C"){
processC();
}
else if(type.equals "D"){
processD();
}
return new Point();
}
protected void processA(){
}
protected void processB(){
}
protected void processC(){
}
protected void processD(){
}
}
//采用设计模式后的代码
public abstract class Strategy{
public abstract String calculate(float a,float b);
}
public class StrategyA extends Strategy{
public String calculate(float a,float b){
//......
}
}
public class StrategyB extends Strategy{
public String calculate(float a,float b){
//......
}
}
public class StrategyC extends Strategy{
public String calculate(float a,float b){
//......
}
}
public class StrategyD extends Strategy{
public String calculate(float a,float b){
//......
}
}
public class Context{
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public String calculate(float a,float b){
//调用具体的子策略的execute();
return strategy.execute(a,b);
}
}
public class Test{
public static void main(String[] args){
float a = 200;
float b = 50;
Context context = new Context(new StrategyA());
context.execute(a,b);
Context context = new Context(new StrategyB());
context.execute(a,b);
Context context = new Context(new StrategyC());
context.execute(a,b);
Context context = new Context(new StrategyD());
context.execute(a,b);
}
}
10、代理
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
//抽象角色:声明真实对象和代理对象的共同接口;
public abstract class Subject{
public abstract void request();
}
public class RealSubject extends Subject{
public void request{
}
}
//代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装
public class ProxySubject extends Subject{
//真实主题
private RealSubject realSubject;
public ProxySubject(){
}
public void request{
//......附加操作
if(null != realSubject){
realSubject = new RealSubject();
realSubject.request();
}
//....附加操作
}
}
java的动态代理
public interface Subject{
public void request();
}
public class RealSubject implements Subject{
public void request{
//.......
}
}
//动态代理角色
public class DynamicProxySubject implements InvocationHandler{
private Object subject;
public DynamicProxSubject(){
}
//被代理的对象
public DynamicProxySubject(Object obj){
this.subject = obj;
}
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
//之前加上一些处理
return method.invoke(subject,args);
//之后加上一些处理
}
//传入被代理对象,返回代理商对象
public Object bind(Object subject){
reuturn Proxy.newProxyInstance(subject.getClass().getClassLoader(),subject.getClass().getInterfaces(),this);
}
}
public class Test{
public static void main(String[] arg){
//被代理对象,也是真实主题
RealSubject realSubject = new RealSubject();
DynamicProxySubject dynamicProxy = new DynamicProxySubject(realSubject);
Subject proxy = (Subject)dynamicProxy.bind(realSubject);
proxy.request();
}
}
//动态代理在日志模块中的运用
public interface BusinessInterface{
public void proceeBusiness();
}
public class BusinessObject implements BusinessInterface{
/**
*private Logger logger = Logger.getLogger(this.getClass().getName());
*public void processBusiness(){
* logger.info("begin process...");
* //....... this is business logic
* logger.info("after process...");
*}
*/
//运用代理之后,日志移至代理类中
public void processBusiness(){
//......this is business logic here;
Sysem.out.println("business logic......");
}
}
public class LoggerProxy implements InvocationHandler{
private Logger logger = Logger.getLogger(this.getClass().getName());
//被代理对象
private Object origin;//.....这里是BusinessObject的实现
public LoggerProxy(Object origin){
this.origin = origin;
}
public Object invoke(Object proxy,Method method,Ojbect[] args){
//所有对日志的处理移至这里
Object obj = null;
logger.info("method before..." + method);
obj = origin.invoke(origin,method,args);
logger.info("method after..." + method);
//返回方法的返回值
return obj;
}
//返回代理对象,this指代LoggerProxy,origin是BusinessInterface的实现
public Object bind(Object origin){
return Proxy.newProxyInstance(origin.getClass().getClassLoader(),origin.getClass.getInterfaces(),this);
}
}
public class Test{
public static void main(String[] args){
BusinessInterface businessObj = new BusinessObject();
LoggerProxy dynamicProxy = new LoggerProxy(businessObj );
BusinessInterface proxyObj = (BusinessInterface)dynamicProxy.bind(businessObj);
proxyObj.processBusiness();
//print result
//method before........
//business logic......
//method after.......
}
}
11、责任链模式
//抽象类中包含一个具体子类对象的引用
public abstract class Handler{
//下一个处理者
protected Handler successor;
//处理请求
public void handleRequest(Request request){
//如果下家处理者存在
if(successor!=null){
successor.next();
}
}
public Handler getSuccessor(){
return successor;
}
public void setSuccessor(Handler successor){
this.successor = success
}
}
//具体处理者持有下家处理者的引用
public class ConcreteHandlerA{
public ConcreteHandlerA(Handler successor){
this.setSuccessor(successor);
}
public absract void handleRequest(Request request){
if(request.type=="1"){
//....处理请求
}else{
//交给下家管理者
getSuccessor().handleRequest(request);
}
}
}
//具体处理者持有下家处理者的引用
public class ConcreteHandlerB{
public ConcreteHandlerB(Handler successor){
this.setSuccessor(successor);
}
public absract void handleRequest(Request request){
if(request.type=="2"){
//处理请求
}else{
//如果下家处理者存在,交给下家管理者
getSuccessor().handleRequest(request);
}
}
}
//具体处理者持有下家处理者的引用
public class ConcreteHandlerC{
public ConcreteHandlerC(Handler successor){
this.setSuccessor(successor);
}
public absract void handleRequest(Request request){
if(request.type=="3"){
//处理请求
}else{
//如果下家处理者存在,交给下家管理者
getSuccessor().handleRequest(request);
}
}
}
public class Request{
}
public class Client{
private static Handler handler1,handler2;
public static void main(String args){
handler1 = new ConcreteHandlerA(null);
handler2 = new ConcreteHandlerB(handler1);
handler3 = new ConcreteHandlerC(handler2);
handler1.handleRequest(new Request());
}
}