Java設計模式之結構模式
一、外觀模式
分析:外觀模式是為子系統的一組接口提供一個統一的界面,數據庫JDBC連接應用就是外觀模式的一個典型例子,
特點:降低系統的復雜度,增加靈活性。
結果:代碼示例:
public class DBCompare { Connection conn = null; PreparedStatement prep = null; ResultSet rset = null; try { Class.forName( "<driver>" ).newInstance(); conn = DriverManager.getConnection( "<database>" ); String sql= "SELECT * FROM <table> WHERE <column name> = ?"; prep = conn.prepareStatement( sql ); prep.setString( 1, "<column value>" ); rset = prep.executeQuery(); if( rset.next() ) { System.out.println( rset.getString( "<column name" ) ); } } catch( SException e ) { e.printStackTrace(); }finally { rset.close(); prep.close(); conn.close(); } } ----------------------- -- 修改後的統一接口 public class DBCompare { String sql = "SELECT * FROM <table> WHERE <column name> = ?"; try { Mysql msql=new mysql(sql); msql.setString( 1, "<column value>" ); rset= msql.executeQuery(); if( rset.next() ) { System.out.println( rset.getString( "<column name" ) ); } } catch( SException e ) { e.printStackTrace(); } finally { mysql.close(); mysql=null; } }
二、代理模式
分析:代理模式是比較有用途的一種模式,而且變種多樣,用途從小的架構設計到系統的大架構設計基本上都覆蓋了,
為什麽需要使用代理模式?一、授權機制(訪問權限) 二、某個客戶端不能直接操作到那個對象,但又和那個對象有所互動(
通過中間代理處理這種操作)。
結果:代碼示例:
-- 定義權限的用戶 public class ForumPermissions implements Cacheable { /** * Permission to read object. */ public static final int READ = 0; /** * Permission to administer the entire sytem. */ public static final int SYSTEM_ADMIN = 1; /** * Permission to administer a particular forum. */ public static final int FORUM_ADMIN = 2; /** * Permission to administer a particular user. */ public static final int USER_ADMIN = 3; /** * Permission to administer a particular group. */ public static final int GROUP_ADMIN = 4; /** * Permission to moderate threads. */ public static final int MODERATE_THREADS = 5; /** * Permission to create a new thread. */ public static final int CREATE_THREAD = 6; /** * Permission to create a new message. */ public static final int CREATE_MESSAGE = 7; /** * Permission to moderate messages. */ public static final int MODERATE_MESSAGES = 8; ..... public boolean isSystemOrForumAdmin() { return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]); } ..... } -- 只有管理員才有權限操作 public class ForumProxy implements Forum { private ForumPermissions permissions; private Forum forum; this.authorization = authorization; public ForumProxy(Forum forum, Authorization authorization, ForumPermissions permissions) { this.forum = forum; this.authorization = authorization; this.permissions = permissions; } ..... public void setName(String name) throws UnauthorizedException, ForumAlreadyExistsException { //只有是系統或論壇管理者才可以修改名稱 if (permissions.isSystemOrForumAdmin()) { forum.setName(name); } else { throw new UnauthorizedException(); } }
三、適配器模式
說明:適配器模式是將兩個不兼容的類糾合在一起使用,同時也屬於結構性模式,一個是適配者和寧一個是被適配者兩者
身份結合在一起。
為何使用?
我們經常會遇到兩個沒有關系的類會聯系在一起使用,第一個解決方法就是,修改各自的接口類,但是我們沒有源代碼,或者,我們
不會為了一個應用修改這個接口類,那這種情況下,就該考慮使用適配器模式
如何使用?
用組合和繼承的方法去使用該模式
結果:代碼示例:
-- 兩個沒有關系的類 public class SquarePeg{ public void insert(String str){ System.out.println("SquarePeg insert():"+str); } } public class RoundPeg{ public void insertIntohole(String msg){ System.out.println("RoundPeg insertIntoHole():"+msg); } } -- 繼承關系實現 public class PegAdapter extends SquarePeg{ private RoundPeg roundPeg; public PegAdapter(RoundPeg peg)(this.roundPeg=peg;) public void insert(String str){super.insert(str); roundPeg.insertIntoHole(str);} } --第二種方式,通過接口實現的方式 -- 兩個沒有聯系的接口類 public interface IRoundPeg{ public void insertIntoHole(String msg); } public interface ISquarePeg{ public void insert(String str); } -- 實現該接口的方法和熟悉 public class SquarePeg implements ISquarePeg{ public void insert(String str){ System.out.println("SquarePeg insert():"+str); } } public class RoundPeg implements IRoundPeg{ public void insertIntohole(String msg){ System.out.println("RoundPeg insertIntoHole():"+msg); } } -- 適配器模式類,實現兩個沒有聯系的接口類 public class PegAdapter implements IRoundPeg,ISquarePeg{ private RoundPeg roundPeg; private SquarePeg squarePeg; // 構造方法 public PegAdapter(RoundPeg peg){this.roundPeg=peg;} // 構造方法 public PegAdapter(SquarePeg peg)(this.squarePeg=peg;) public void insert(String str){ roundPeg.insertIntoHole(str);} }
四、組合模式
分析:組合模式可以這樣理解,在我們程序中常用的js前端的應用,大部分都是樹型結構的,而組合模式就相當於
樹型結構的模式,通過叠代器遍歷出來。
組合模式的優勢:使客戶端調用簡單,更容易在組合過程中加入部件屬性和方法。
結果:代碼示例:
---定義抽象類 public abstract class Equipment { private String name; //實價 public abstract double netPrice(); //折扣價格 public abstract double discountPrice(); //增加部件方法 public boolean add(Equipment equipment) { return false; } //刪除部件方法 public boolean remove(Equipment equipment) { return false; } //註意這裏,這裏就提供一種用於訪問組合體類的部件方法。 public Iterator iter() { return null; } public Equipment(final String name) { this.name=name; } } -- 繼承該抽象類 public class Disk extends Equipment { public Disk(String name) { super(name); } //定義Disk實價為1 public double netPrice() { return 1.; } //定義了disk折扣價格是0.5 對折。 public double discountPrice() { return .5; } }
五、裝飾者模式
分析:裝飾者模式是給對象添加額外的一些職責,就像在墻上刷油漆,使用裝飾者模式比生成子類實現的都靈活
為什麽要使用裝飾者模式?
我們通常可以繼承來實現功能的拓展,若這些功能的拓展比較多,那麽勢必生成很多子類,增加系統的復雜性,
使用裝飾者模式可以將一些功能動態的加入,提供了"即插即用"的方法,在程序運行期間可以隨時插入新增一些
功能。
結果:代碼示例
----定義接口 public interface Work { public void insert(); } --接口類的實現 public class SquarePeg implements Work{ public void insert(){ System.out.println("方形樁插入"); } } --裝飾者模式額外添加的功能 public class Decorator implements Work{ private Work work; //額外增加的功能被打包在這個List中 private ArrayList others = new ArrayList(); //在構造器中使用組合new方式,引入Work對象; public Decorator(Work work) { this.work=work; others.add("挖坑"); others.add("釘木板"); } public void insert(){ newMethod(); } //在新方法中,我們在insert之前增加其他方法,這裏次序先後是用戶靈活指定的 public void newMethod() { otherMethod(); work.insert(); } public void otherMethod() { ListIterator listIterator = others.listIterator(); while (listIterator.hasNext()) { System.out.println(((String)(listIterator.next())) + " 正在進行"); } } }
六、橋接模式
分析:任何事物對象都有抽象和行為之分,例如人,人是一種抽象,人分男人和女人等;人有行為,行為也有各種體現,
所以,人與人的行為這兩個概念也反映了抽象與行為之分。在面向對象設計中,對象概念實際是由屬性與行為兩個部分組成的,
屬性我們可以認為是一種靜止的,是一種抽象,一般情況下,行為是包含在一個對象中的,但是,在有的情況下,
我們需要將這些行為也進行歸類,形成一個總的行為接口,這也是橋接模式的優勢。
為什麽使用橋接模式?
不希望抽象部分和行為有一種固定的綁定聯系,而是應該可以動態聯系的。
結果:代碼示例:
-- 抽象接口類
public abstract class Coffee
{
CoffeeImp coffeeImp;
public void setCoffeeImp() {
this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();
}
public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}
public abstract void pourCoffee();
}
public abstract class CoffeeImp
{
public abstract void pourCoffeeImp();
}
--- 繼承類
public class MediumCoffee extends Coffee
{
public MediumCoffee() {setCoffeeImp();}
public void pourCoffee()
{
CoffeeImp coffeeImp = this.getCoffeeImp();
//我們以重復次數來說明是沖中杯還是大杯 ,重復2次是中杯
for (int i = 0; i < 2; i++)
{
coffeeImp.pourCoffeeImp();
}
}
}
//大杯
public class SuperSizeCoffee extends Coffee
{
public SuperSizeCoffee() {setCoffeeImp();}
public void pourCoffee()
{
CoffeeImp coffeeImp = this.getCoffeeImp();
//我們以重復次數來說明是沖中杯還是大杯 ,重復5次是大杯
for (int i = 0; i < 5; i++)
{
coffeeImp.pourCoffeeImp();
}
}
}
-- 主方法
public static void main(String[] args){
MediumCoffee mediumCoffee = new MediumCoffee();
mediumCoffee.pourCoffee();
}
七、享元模式
分析:享元模式是避免大量擁有相同的小類的開銷(如耗費內存),使大家共享一個類(元類)
為什麽使用?
該模式是提高效率和性能的模式,會大大加快程序的運行速度,應用場合很多,比如你要從數據庫讀取一系列
字符竄,這些字符竄是有許多是重復的,因此,將這些字符竄存儲在池中。
結果:代碼示例:
--接口定義 public interface Flyweight { public void operation( ExtrinsicState state ); } //用於本模式的抽象數據類型(自行設計) public interface ExtrinsicState { } --實現該接口 public class ConcreteFlyweight implements Flyweight { private IntrinsicState state; public void operation( ExtrinsicState state ) { //具體操作 } } -- 享元模式類 public class FlyweightFactory { //Flyweight pool private Hashtable flyweights = new Hashtable(); public Flyweight getFlyweight( Object key ) { Flyweight flyweight = (Flyweight) flyweights.get(key); if( flyweight == null ) { //產生新的ConcreteFlyweight flyweight = new ConcreteFlyweight(); flyweights.put( key, flyweight ); } return flyweight; } } -- 主方法(實現 享元模式) public static void main(String[] args) { FlyweightFactory factory = new FlyweightFactory(); Flyweight fly1 = factory.getFlyweight( "Fred" ); Flyweight fly2 = factory.getFlyweight( "Wilma" ); }
Java設計模式之結構模式