面向对象:
- 松耦合
- 高内聚
面向对象系统追求的目标就是尽可能地提高系统模块内部的内聚(Cohesion)、尽可能降低模块间的耦合(Coupling) 。然而这也是面向对象设计过程中最难把握的部分。
GOF在提出Bridge模式的时候指出:Bridge模式的用意是“将 抽象化(Abstraction) 与 实现化(Implementation) 脱耦,使得二者可以独立地变化”。
耦合和脱耦
- 耦合就是两个实体的行为的某种强关联。
- 将它们的强关联去掉,就是耦合的解脱,或称脱耦。
脱耦是指将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联改换成弱关联。
- 将两个角色之间的继承关系改为聚合关系,就是将它们之间的强关联改换成为弱关联。
- 桥连模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以相对独立地变化。这就是桥连模式的用意。
模式结构
- 由抽象化角色和修正抽象化角色组成的抽象化等级结构。
- 由实现化角色和两个具体实现化角色所组成的实现化等级结构。
- 在桥接模式中的桥接是单向的,也就是只能是抽象部分的对象去使用具体实现部分的对象,而不能反过来。也就是个单向桥。
- 使用Bridge模式和原始解决方案的根本区别在于是通过继承还是通过合成\聚合的方式去实现一个功能需求。因此面向对象分析和设计中有一个原则就是:
Favor Composition Over lnheritance
(类似继承但不是继承)
模式代码
using System;
namespace 桥接模式
{
abstract class Implementor
{
public abstract void Operation();
}
class ConcreteImplementorA:Implementor
{
public override void Operation()
{
Console.WriteLine("具体实现A的方法执行");
}
}
class ConcreteImplementorB:Implementor
{
public override void Operation()
{
Console.WriteLine("具体实现B的方法执行");
}
}
class Abstraction
{
protected Implementor implementor;
public void SetImplementor(Implementor implementor)
{
this.implementor = implementor;
}
public virtual void Operation()
{
implementor.Operation();
}
}
class RefinedAbstraction:Abstraction
{
public override void Operation()
{
implementor.Operation();
}
}
class Program
{
static void Main(string[] args)
{
Abstraction ab = new RefinedAbstraction();
ab.SetImplementor(new ConcreteImplementorA());
ab.Operation();
ab.SetImplementor(new ConcreteImplementorB());
ab.Operation();
Console.Read();
}
}
}
本质
分离抽象和实现
举例
ps:仅代表个人思路
【问题】
考虑这样一个实际的业务功能:发送提示消息。
- 基本上所有带业务流程处理的系统都会有这样的功能,比如某人有新的工作了,需要发送一条消息提示他。
- 从业务_上看,消息又分成普通消息、加急消息和特急消息多种,不同的消息类型,业务功能处理是不-样的,比如加急消息是在消息上添加加急,而特急消息除了添加特急外,还会做一条催促的记录,多久不完成会继续催促。从发送消息的手段上看,又有系统内短消息、手机短消息、邮件等等。
现在要实现这样的发送提示消息的功能,该如何实现呢?
【代码】
public class MyAuthenticator extends Authenticator {
private String userName=null;
private String password=null;
public MyAuthenticator(){}
public MyAuthenticator(String username, String password) {
this.userName = username;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(userName, password);
}
}
public abstract class AbstractMessage {
protected MessageImplementor impl;
public AbstractMessage(MessageImplementor impl) {
super();
this.impl = impl;
}
public void sendMessage(String message,String toUser) {
this.impl.send(message, toUser);
}
}
public class CommonMessage extends AbstractMessage {
public CommonMessage(MessageImplementor impl) {
super(impl);
}
public void sendMessage(String message,String toUser) {
super.sendMessage(message, toUser);
}
}
public class UrgencyMessage extends AbstractMessage {
public UrgencyMessage(MessageImplementor impl) {
super(impl);
}
public void sendMessage(String message,String toUser) {
message="加急:"+message;
super.sendMessage(message, toUser);
}
public Object watch(String messageld) {
return null;
}
}
public class SpecialUrgencyMessage extends AbstractMessage {
public SpecialUrgencyMessage(MessageImplementor impl) {
super(impl);
}
public void sendMessage(String message,String toUser) {
message="特急:"+message;
super.sendMessage(message, toUser);
}
public void hurry(String messageld) {
}
}
public interface MessageImplementor {
public void send(String message,String toUser);
}
public class MessageSMS implements MessageImplementor {
@Override
public void send(String message, String toUser) {
System.out.println("使用站内短消息的方式,发送消息:"+message+"给"+toUser);
}
}
public class MessageMobile implements MessageImplementor {
@Override
public void send(String message, String toUser) {
System.out.println("使用手机短消息的方式,发送消息:"+message+"给"+toUser);
}
}
public class MessageEmail implements MessageImplementor {
@Override
public void send(String message, String toUser) {
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.163.com"); //smtp服务器地址
props.put("mail.smtp.auth", true); //是否需要认证
MyAuthenticator myauth = new MyAuthenticator("lavinia_dv1005@163.com","********");
Session session = Session.getInstance(props,myauth);
session.setDebug(true); //打开debug功能
Message msg = new MimeMessage(session);
try {
msg.setFrom(new InternetAddress("lavinia_dv1005@163.com"));//设置发件人
msg.setText(message); //设置邮件内容
msg.setSubject(message); //设置邮件主题
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(toUser));
Transport.send(msg);
} catch(AddressException e) {
System.out.println("地址错误!");
e.printStackTrace();
} catch(MessagingException e) {
System.out.println("信息错误!");
e.printStackTrace();
}
}
}
public class Client {
public static void main(String[] args) {
MessageImplementor impl =new MessageSMS();
AbstractMessage m=new CommonMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
m=new UrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
m=new SpecialUrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
impl=new MessageMobile();
m=new CommonMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
m=new UrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
m=new SpecialUrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
impl=new MessageEmail();
m=new CommonMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
m=new UrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
m=new SpecialUrgencyMessage(impl);
m.sendMessage("请喝一杯茶", "dv17866703607@163.com");
}
}
【UML图】