漫谈设计模式(三):桥接(Bridge)模式 —— 将类功能、结构两层次分离

1.前言

类主要有两个层次,一个是功能层次,另一个是实现层次。

功能层次,一般应用于当前类不能满足多样化的业务需求,让子类去继承(具体)父类,添加加一些父类中没有的功能(一般是增加新的方法),这就属于因增加新功能而产生的层次结构。

实现层次,一般常见于子类去继承抽象类或接口,将抽象类或接口中的抽象方法重写,抽象类(接口)只声明了方法,而具体任务的分担需要子类去分担。相当于,子类只是将父类宣传出的口号、吹出的牛逼给落实了,将分配的任务给真正去做了,但它并没有增加新功能,只是实现父类的抽象方法,这就是类的实现层次。

若这两个层次在同一个类中实现,这就会将两种层次结构混杂在一起,相互影响,耦合度高,不利后期拓展。桥接模式就是将这两种层次分开,分别在两个类中实现,某一个层次的修改不会影响到另一个层次的实现。

2.代码实现

1).先定义一普通的POJO实体类Product

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.math.BigDecimal;
 
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
 
@Setter
@Getter
@ToString
@NoArgsConstructor
public class Product {
    private Integer id;//产品id
    private String name;// 产品名
    private String description;// 描述
    private BigDecimal price;// 价格
 
    public Product(String name) {
        super();
        this.name = name;
    }
    public Product(BigDecimal price) {
        super();
        this.price = price;
    }
    public Product(Integer id, String name, String description) {
        super();
        this.id = id;
        this.name = name;
        this.description = description;
    }
    public Product(Integer id, String name, String description, BigDecimal price) {
        super();
        this.id = id;
        this.name = name;
        this.description = description;
        this.price = price;
    }
}

 

2).定义一个操作实体类Product的Dao层接口。这个接口有基本的增删改查的抽象方法。

1
2
3
4
5
6
7
8
import java.util.List;
 
public interface ProductDao {
    int addProduct(Product product);
    int deleteProduct(int productId);
    int modifyProduct(Product product);
    List<Product> findProducts(Product product);
}

  

3).增加实现

随着客户对数据库的需求的变化,整个软件生命周期后期可能不只使用一种数据库,可能要编写在不同数据库平台上进行数据持久化操作的ProductDao实现类

复制代码
/**
 * 在Oracle数据库的实现
 * @author Administrator
 *
 */
public class ProductDaoOrancleImpl implements ProductDao {

    @Override
    public int addProduct(Product product) {
        System.out.println("在Orancle数据库中保存了一个产品"+product);
        return 1;
    }

    @Override
    public int deleteProduct(int productId) {
        System.out.println("在Orancle数据库中删除了一个产品,其id为"+productId);
        return 1;
    }

    @Override
    public int modifyProduct(Product product) {
        System.out.println("在Orancle数据库中修改了一个产品,修改后为"+product);
        return 1;
    }

    @Override
    public List<Product> findProducts(Product product) {
        Product p1=new Product(1, "洗衣机", "好用便宜的洗衣机");
        Product p2=new Product(2, "T恤", "透气清爽的T恤");
        System.out.println("从Orancle数据库中查询出的产品有:{"+p1+"},{"+p2+"}");
        return Arrays.asList(p1,p2);
    }

}
在Oracle数据库的实现
复制代码
复制代码
import java.util.Arrays;
import java.util.List;
/**
 * 在mysql数据库的实现
 * @author Administrator
 *
 */
public class ProductDaoMysqlImpl implements ProductDao{

    @Override
    public int addProduct(Product product) {
        System.out.println("在mysql数据库中保存了一个产品"+product);
        return 1;
    }

    @Override
    public int deleteProduct(int productId) {
        System.out.println("在mysql数据库中删除了一个产品,其id为"+productId);
        return 1;
    }

    @Override
    public int modifyProduct(Product product) {
        System.out.println("在mysql数据库中修改了一个产品,修改后为"+product);
        return 1;
    }

    @Override
    public List<Product> findProducts(Product product) {
        Product p1=new Product(1, "洗衣机", "好用便宜的洗衣机");
        Product p2=new Product(2, "T恤", "透气清爽的T恤");
        System.out.println("在mysql数据库中查询出的产品有:{"+p1+"},{"+p2+"}");
        return Arrays.asList(p1,p2);
    }
}
在mysql数据库的实现
复制代码

 

4.编写一个实现桥接功能并抽象化的具体类

这个类的关键在于委托机制,委托成员变量productDao去完成实际业务处理。当然productDao一定是ProductDao接口的实现类的实例对象,因为接口不能实例化。这个成员变量productDao是完成桥接的关键,它将接口被实现的方法ProductDaoBridge的子类可能出现的拥有新功能的方法给连接在了一起。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.List;
 
public class ProductDaoBridge {
    //被final修饰,初始化后不能去引用其他ProductDao对象
    protected final ProductDao productDao;
 
    public ProductDaoBridge(ProductDao productDao) {
        super();
        this.productDao = productDao;
    }
 
    public int addProduct(Product product) {
         
        return productDao.addProduct(product);
    }
     
    int deleteProduct(int productId) {
        return productDao.deleteProduct(productId);
    }
     
    int modifyProduct(Product product) {
        return productDao.modifyProduct(product);
         
    }
    List<Product> findProducts(Product product){
        return productDao.findProducts(product);
    }
}

  

5).增加功能

业务处理中频繁要先查数据再进行删除,在子类中可以新增一个方法,将查删操作一并处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.List;
 
public class MultiProductDaoBridge extends ProductDaoBridge {
 
    public MultiProductDaoBridge(ProductDao productDao) {
        super(productDao);
    }
 
    /**
     * 查出查询后,全部删除
     *
     * @param product 查询条件
     */
    //final修饰防止被子类重写
    public final int[]  findProductThenDelete(Product product) {
        List<Product> products = this.productDao.findProducts(product);
        int[] delOks = new int[products.size()];
        for (int i = 0; i < products.size(); i++) {
            delOks[i] = productDao.deleteProduct(products.get(i).getId());
        }
        return delOks;
    }
 
}

  

 


作者:蜀中孤鹰
个性签名:技术如逆水行舟,不进则退;若持之以恒,则水滴穿石。

             IT新手,水平有限,谬误疏漏之处,敬请谅解哦! 

posted @ 2019-08-15 01:02  蜀中孤鹰  阅读(375)  评论(0)    收藏  举报
编辑推荐:
· 从 Redis 客户端超时到 .NET 线程池挑战
· C23和C++26的#embed嵌入资源指南
· 「EF Core」框架是如何识别实体类的属性和主键的
· 独立开发,这条路可行吗?
· 我在厂里搞 wine 的日子
阅读排行:
· 他没买 iPad,而是花了半年时间,为所有“穷学生”写了个笔记神器
· Visual Studio 现已支持新的、更简洁的解决方案文件(slnx)格式
· 只需一行命令,Win11秒变Linux开发主机!
· 上周热点回顾(7.7-7.13)
· 也是出息了,业务代码里面也用上算法了。
点击右上角即可分享
微信分享提示