结构型的设计模式:
适配器模式是各种模式的起源。
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;
}
}
}
通过连接池的管理,实现了数据库连接的共享,不需要每一次都要重新创建连接,节省数据库重新创建的开销,提高系统的性能。