装饰者模式
装饰者模式的话相对简单一些,其中只有两个重要的角色,一个是被装饰者,一个就是装饰器。
下面来看一个例子。在这个例子当中,被装饰者是Human类(这里Human是以一种接口的形式)的对象(当然也包括Human类的子类),装饰器是我们自定义的一些类名,只是逻辑上抽象出来的,就暂且叫它们Decorator_first、Decorator_second。。。。等,而这些类都是Decorator接口的实现类。
以下是代码例子:
1.定义一个接口
package decorator;
public interface Human {
void wearClothes();
void goAndPlay();
}
2.实现改接口的抽象类
package decorator;
public abstract class Decorator implements Human{
}
3.定义一个装饰器Decorator_first
package decorator;
public class Decorator_first extends Decorator{
Human human;
public Decorator_first(Human human) {
this.human = human;
}
void methodsForWearingClothes(){
System.out.println("先起床");
System.out.println("找衣服");
System.out.println("穿衣服");
}
@Override
public void wearClothes() {
this.human.wearClothes();
methodsForWearingClothes();
}
@Override
public void goAndPlay() {
this.human.goAndPlay();
}
}
4.定义一个装饰器Decorator_second
package decorator;
public class Decorator_second extends Decorator{
Human human;
public Decorator_second(Human human) {
this.human = human;
}
void methodsForGoingToPlay(){
System.out.println("找地图");
System.out.println("找自己喜欢的地方");
System.out.println("出发");
}
@Override
public void wearClothes() {
this.human.wearClothes();
}
@Override
public void goAndPlay() {
this.human.goAndPlay();
methodsForGoingToPlay();
}
}
5.测试类
package decorator;
public class Test {
public static void main(String[] args) {
Human human=new Human() {
@Override
public void wearClothes() {
System.out.println("想要穿衣服");
}
@Override
public void goAndPlay() {
System.out.println("我想要出去玩");
}
};
human=new Decorator_second(new Decorator_first(human));
human.wearClothes();
human.goAndPlay();
}
}
6.测试结果
想要穿衣服
先起床
找衣服
穿衣服
我想要出去玩
找地图
找自己喜欢的地方
出发
1.这里为了对被装饰者进行装饰,将装饰者聚合在了装饰器类中(或者是装饰器接口的实现类中)
2.为了实现装饰完被装饰者后能够再次装饰,需要装饰器本身就是被装饰者类的继承类或者是实现类,所以这里Decorator本身就是一个Human,这里是用了实现,而Decorator作为一个抽象类,不做任何具体实现
桥接模式
先分享一个图:
桥接模式的本质还是聚合,利用java的多态特性。
首先是有右侧Implementor的实现树,然后在抽象层中的Abstraction类中聚合了Implementor这个多态对象,而在Abstraction这棵继承树上可以再对聚合的Implementor这个对象进行更多的处理,比如RefinedAbstraction通过继承的方式以对implementor在另一个维度进行拓展。
代码例子:
1.一个电子器件的接口
package bridge2;
public interface Electronics {
void printName(String brand);
}
2.电子器件有不同的实现类,例如手机、电视机、电冰箱。。。
package bridge2;
public class Phone implements Electronics{
@Override
public void printName(String brand) {
System.out.println("我是一个手机,品牌是;"+brand);
}
}
package bridge2;
public class Refrigirator implements Electronics{
@Override
public void printName(String brand) {
System.out.println("我是一个电冰箱,品牌是;"+brand);
}
}
package bridge2;
public class Televition implements Electronics{
@Override
public void printName(String brand) {
System.out.println("我是一个电视机,品牌是;"+brand);
}
}
3.上面是对电子器件在产品品类上的拓展,如果想要在品牌上再进行拓展:
package bridge2;
public abstract class ElectronicsWithBrand {
Electronics electronics;
String brand;
public ElectronicsWithBrand(Electronics electronics) {
this.electronics = electronics;
}
public void sayNameWithBrand() {
this.electronics.printName(this.brand);
}
}
4.拓展不同的品牌
package bridge2;
public class HuaweiPhone extends ElectronicsWithBrand{
public HuaweiPhone(Electronics electronics) {
super(electronics);
this.brand="huawei";
}
}
package bridge2;
public class SamsungPhone extends ElectronicsWithBrand{
public SamsungPhone(Electronics electronics) {
super(electronics);
this.brand="samsung";
}
}
5.测试
package bridge2;
public class Test {
public static void main(String[] args) {
ElectronicsWithBrand samsungPhone=new SamsungPhone(new Phone());
samsungPhone.sayNameWithBrand();
ElectronicsWithBrand huaweiPhone=new HuaweiPhone(new Phone());
huaweiPhone.sayNameWithBrand();
}
}
6.测试结果
我是一个手机,品牌是;samsung
我是一个手机,品牌是;huawei
jdbc的话感觉并不是桥接模式,更多的是一个工厂模式:
private static Connection getConnection(
String url, java.util.Properties info, Class<?> caller) throws SQLException {
/*
* When callerCl is null, we should check the application's
* (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here.
*/
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
// synchronize loading of the correct classloader.
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
if(url == null) {
throw new SQLException("The url cannot be null", "08001");
}
println("DriverManager.getConnection(\"" + url + "\")");
// Walk through the loaded registeredDrivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
// if we got here nobody could connect.
if (reason != null) {
println("getConnection failed: " + reason);
throw reason;
}
println("getConnection: no suitable driver found for "+ url);
throw new SQLException("No suitable driver found for "+ url, "08001");
}
这里从registeredDrivers中找到对应的Driver的实现类对象后,调用connect可以获得到对象的Connection的实现类对象,而不同的Connection实现类对象具体的操作数据库的方式必然不同。
那因为不同的数据库操作方式肯定不同,所以不同的数据库驱动会对应获得到不同的Connection实现类对象,这里也是用了多态的概念,只有这里有一点桥接模式的影子。事实上桥接模式解决的问题是防止类爆炸,实现对一个抽象概念在不同维度上的拓展。而jdbc驱动这块更像是一个工厂模式。(个人见解,勿喷哈)