结构型的设计模式:
适配器模式是各种模式的起源。
1】适配器模式(Adapter):
适配器模式是将某个类的接口转换成客户端期望的另一个接口表示,目的就是消除由于接口的不匹配所造成的类的兼容性的问题。
类的适配器模式;接口的适配器模式;对象的适配器模式。
类的适配器模式:
类的适配器模式的思想是通过继承一个类的形式去实现里面的方法。
package com.mjf.model.adapter; public class Adapter extends Source implements Target { @Override public void method2() { // TODO Auto-generated method stub System.out.println("this is method2"); } } package com.mjf.model.adapter; public class Source { public void method1(){ System.out.println("this is method1"); } } package com.mjf.model.adapter; public interface Target { public void method1(); public void method2(); } /** 测试类 */ package com.mjf.test.adapter; import com.mjf.model.adapter.Adapter; import com.mjf.model.adapter.Target; public class AdapterTest { public static void main(String[] args) { Target ta = new Adapter(); ta.method1(); ta.method2(); } }
对象的适配器模式:
基本的思路是和类的适配器模式相似,只是不需要再继承类,而是在实例类中定义了另一个类的实例来初始化,以达到解决兼容性的问题。
package com.mjf.model.adapter; public interface Target { public void method1(); public void method2(); } package com.mjf.model.adapter; public class Adapter2 implements Target { private Source source; public Adapter2(Source source){ this.source = source; } @Override public void method2() { // TODO Auto-generated method stub System.out.println("this is method2"); } @Override public void method1() { // TODO Auto-generated method stub source.method1(); } } /** 测试类 */ package com.mjf.test.adapter; import com.mjf.model.adapter.Adapter2; import com.mjf.model.adapter.Source; import com.mjf.model.adapter.Target; public class AdapterTest2 { public static void main(String[] args) { Source source = new Source(); Target adapter = new Adapter2(source); adapter.method1(); adapter.method2(); } }
接口的适配器模式:
在实际的开发中,有时我们写的一个接口中有多个抽象的方法,当我们写该接口的实现类时,就必须要实现该接口的所有方法;而我们只是需要其中的一些方法。
所以有了接口的适配器模式,借助于抽象类实现该接口,需要什么方法则定义类来继承该抽象类即可。
package com.mjf.model.adapter; public interface Source02 { public void method1(); public void method2(); } package com.mjf.model.adapter; public abstract class AbstractAdapter implements Source02 { public void method1(){}; public void method2(){}; } package com.mjf.model.adapter; public class Warpper01 extends AbstractAdapter { @Override public void method1() { System.out.println("this is method1"); } } package com.mjf.model.adapter; public class Warpper02 extends AbstractAdapter { @Override public void method2() { System.out.println("this is method2"); } } / ** 测试类 */ package com.mjf.test.adapter; import com.mjf.model.adapter.Warpper01; import com.mjf.model.adapter.Warpper02; public class AdapterTest3 { public static void main(String[] args) { Warpper01 w1 = new Warpper01(); Warpper02 w2 = new Warpper02(); w1.method1(); w1.method2(); w2.method1(); w2.method2(); } }
三种模式的使用范围:
类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。
对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。
接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。
2】装饰者模式(Decorator):
装饰者模式是给一个对象增加一些新的功能,而且是动态的。要求装饰的对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。
package com.mjf.model.decorator; public interface Sourceable { void method(); } package com.mjf.model.decorator; public class Source implements Sourceable { @Override public void method() { // TODO Auto-generated method stub System.out.println("this is method"); } } package com.mjf.model.decorator; public class Decorator implements Sourceable { private Sourceable source; public Decorator(Sourceable source) { super(); this.source = source; } @Override public void method() { // TODO Auto-generated method stub System.out.println("before decorator!"); source.method(); System.out.println("after decorator!"); } } /** 测试类 */ package com.mjf.test.decorator; import com.mjf.model.decorator.Decorator; import com.mjf.model.decorator.Source; import com.mjf.model.decorator.Sourceable; public class DecoratorTest { public static void main(String[] args) { Sourceable source = new Source(); Sourceable decorator = new Decorator(source); decorator.method(); } }
装饰者模式的范围:需要扩展一个类的功能;
动态的为一个对象增加功能而且还能动态撤销。
不过,会产生过多相似的对象,不容易排错。
3】代理模式(Proxy):
代理模式就是多一个代理类出来,替代原对象进行一些操作。比如相当于说是一个中介的性质,通过中介能够对原对象进行比较详细的了解。
package com.mjf.model.proxy; public interface Source { void method(); } package com.mjf.model.proxy; public class Sou implements Source { @Override public void method() { // TODO Auto-generated method stub System.out.println("the original method!"); } } package com.mjf.model.proxy; public class Proxy implements Source { private Sou sou; public Proxy() { super(); this.sou = new Sou(); } @Override public void method() { before(); sou.method(); atfer(); } private void atfer() { System.out.println("after proxy!"); } private void before() { System.out.println("before proxy!"); } } /** 测试类 */ package com.mjf.test.proxy; import com.mjf.model.proxy.Proxy; import com.mjf.model.proxy.Source; public class ProxyTest { public static void main(String[] args) { Source s = new Proxy(); s.method(); } }
4】外观模式(Facade)
外观模式是为了解决类与类之间的依赖关系,把类之间的关系放在一个外观类中,降低了类之间的耦合度,该模式中不涉及接口。
package com.mjf.model.facade; public class Memory { public void startup(){ System.out.println("memory startup!"); } public void shutdown(){ System.out.println("memory shutdown!"); } } package com.mjf.model.facade; public class Disk { public void startup(){ System.out.println("disk startup!"); } public void shutdown(){ System.out.println("disk shutdown!"); } } package com.mjf.model.facade; public class Cpu { public void startup(){ System.out.println("cpu startup"); } public void shutdown(){ System.out.println("cpu shutdown"); } } package com.mjf.model.facade; public class Computer { private Cpu cpu; private Memory memory; private Disk disk; public Computer(){ cpu = new Cpu(); memory = new Memory(); disk = new Disk(); } public void startup(){ System.out.println("start the computer!"); cpu.startup(); memory.startup(); disk.startup(); System.out.println("start computer finished!"); } public void shutdown(){ System.out.println("begin to close the computer!"); cpu.shutdown(); memory.shutdown(); disk.shutdown(); System.out.println("computer closed!"); } } /** 测试类 */ package com.mjf.test.facade; import com.mjf.model.facade.Computer; public class FacadeTest { public static void main(String[] args) { Computer computer = new Computer(); computer.startup(); computer.shutdown(); } }
如果没有外观类,各个类之间将会相互持有实例产生关系,会造成依赖。当有了外观类就有了解耦的作用。
5】桥接模式(Bridge)
桥接模式是把事物和具体实现分开,使他们可以各自独立的变化。桥接的用意为:将抽象化与实现化解耦,使得两者可以独立变化。
如同JDBC桥接各类数据库一般,提供一个统一的接口,每个数据库提供各自的实现,用数据库驱动程序进行桥接即可。
package com.mjf.model.bridge; public interface Sourceable { void method(); } package com.mjf.model.bridge; public class Source01 implements Sourceable { @Override public void method() { // TODO Auto-generated method stub System.out.println("this is the frist method"); } } package com.mjf.model.bridge; public class Source02 implements Sourceable { @Override public void method() { // TODO Auto-generated method stub System.out.println("this is the second method"); } } package com.mjf.model.bridge; public class Bridge { private Sourceable source; public Sourceable getSource() { return source; } public void setSource(Sourceable source) { this.source = source; } public void method(){ source.method(); } } package com.mjf.model.bridge; public class MyBridge extends Bridge { public void method(){ getSource().method(); } } / ** 测试类 */ package com.mjf.test.bridge; import com.mjf.model.bridge.Bridge; import com.mjf.model.bridge.MyBridge; import com.mjf.model.bridge.Source01; import com.mjf.model.bridge.Source02; import com.mjf.model.bridge.Sourceable; public class BridgeTest { public static void main(String[] args) { Bridge bridge = new MyBridge(); /*调用第一个对象*/ Sourceable source1 = new Source01(); bridge.setSource(source1); bridge.method(); /*调用第二个对象*/ Sourceable source2 = new Source02(); bridge.setSource(source2); bridge.method(); } }
如同JDBC的连接原理为:
6】组合模式(Composite)
组合模式有时又叫部分-整体模式在处理类似树形结构的问题时比较方便。
package com.mjf.model.composite; import java.util.Enumeration; import java.util.Vector; public class TreeNode { private String name; private TreeNode parent; private Vector<TreeNode> children = new Vector<TreeNode>(); public TreeNode(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public TreeNode getParent() { return parent; } public void setParent(TreeNode parent) { this.parent = parent; } //添加孩子节点 public void add(TreeNode node){ children.add(node); } //删除孩子节点 public void remove(TreeNode node){ children.remove(node); } //取得孩子节点 public Enumeration<TreeNode> getChildren(){ return children.elements(); } } /** 测试类 */ package com.mjf.test.composite; import com.mjf.model.composite.TreeNode; public class Tree { TreeNode root = null; public Tree(String name) { root = new TreeNode(name); } public static void main(String[] args) { Tree tree = new Tree("A"); TreeNode nodeB = new TreeNode("B"); TreeNode nodeC = new TreeNode("C"); nodeB.add(nodeC); tree.root.add(nodeB); System.out.println("build the tree finished!"); } }
将多个对象组合在一起进行操作,常用于表示树形结构中,例如二叉树,数等。
7】享元模式(Flyweight)
享元模式的主要目的是实现对象的共享,即共享池。当系统中对象多的时候可以减少内存的开销,一般与工厂模式使用。
FlyWeightFactory负责的是创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象。有;就返回已经存在的对象,没有;则创建一个新的对象。
适用于作共享的一些个对象,他们有一些共有的属性,就是拿数据库连接池来说,url、driverClassName、userName、password和dbName,这些属性对于每个连接来说都是一样的,所以就适用享元模式来处理。
将属性作为内部数据,其他的作为外部数据,在方法调用的时候,当做参数传进来,节省空间,减少实例的数量。
package com.mjf.model.flyweight; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Vector; public class ConnectionPool { private Vector<Connection> pool; /*公有属性*/ private String url = "jdbc:mysql://localhost:3306/test"; private String username = "root"; private String password = "root"; private String driverClassName = "com.mysql.jdbc.Driver"; private int poolSize = 100; private static ConnectionPool instance = null; Connection conn = null; /*构造方法,做一些初始化工作*/ private ConnectionPool() { pool = new Vector<Connection>(poolSize); for (int i = 0; i < poolSize; i++) { try { Class.forName(driverClassName); conn = DriverManager.getConnection(url, username, password); pool.add(conn); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } } /* 返回连接到连接池 */ public synchronized void release() { pool.add(conn); } /* 返回连接池中的一个数据库连接 */ public synchronized Connection getConnection() { if (pool.size() > 0) { Connection conn = pool.get(0); pool.remove(conn); return conn; } else { return null; } } }
通过连接池的管理,实现了数据库连接的共享,不需要每一次都要重新创建连接,节省数据库重新创建的开销,提高系统的性能。