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" ); }