常用設計模式應用場景

[size=large]1、抽象工廠
2、Builder
3、工廠方法(把變和不變的地方隔離出來)
4、Bridge模式
5、適配器Adapter
6、Decarator
7、Command命令模式
8、Visitor模式
9、Strategy模式
10、代理
11、責任鏈模式

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<ProductA> productAList = new ArrayList();
private List<ProductB> productBList = new ArrayList();

private List<ProductC> 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());

}

} [/size]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章