设计模式--组合模式(Composite)

1.Composite模式定义

将对象以树形结构组织起来,以达到“整体-部分”的层次结构。使得客户端对单个对象和组合对象的调用具有一致性

组合体内这些对象都有共同接口,当组合体的一个对象被调用时,Composite将遍历整个树形结构,实现有满足条件的对象调用并返回。

2.Composite模式的优点

  1. 使得客户端的调用简单,客户端可以一致的使用单个对象或者组合对象,用户不必关心自己调用的是单个对象还是组合对象,简化了客户端代码。
  2. 更容易在组合对象内加入其它对象,客户端不必关心新加入了组件而更改自己的代码。

3.例子

eureka 设置实例状态的规则

3.1 定义接口

组合体和单个对象实现此接口。

public interface InstanceStatusOverrideRule {

   /**
    * Match this rule.
    *
    * @param instanceInfo The instance info whose status we care about.
    * @param existingLease Does the instance have an existing lease already? If so let's consider that.
    * @param isReplication When overriding consider if we are under a replication mode from other servers.
    * @return A result with whether we matched and what we propose the status to be overriden to.
    */
   StatusOverrideResult apply(final InstanceInfo instanceInfo,
                              final Lease<InstanceInfo> existingLease,
                              boolean isReplication);

}

3.2 单个对象DownOrStartingRule

/**
* This rule matches if the instance is DOWN or STARTING.
*
* 这个规则匹配 实例是 DOWN的还是starting
* Created by Nikos Michalakis on 7/13/16.
*/
public class DownOrStartingRule implements InstanceStatusOverrideRule {
   private static final Logger logger = LoggerFactory.getLogger(DownOrStartingRule.class);

   @Override
   public StatusOverrideResult apply(InstanceInfo instanceInfo,
                                     Lease<InstanceInfo> existingLease,
                                     boolean isReplication) {
       // ReplicationInstance is DOWN or STARTING - believe that, but when the instance says UP, question that
       // The client instance sends STARTING or DOWN (because of heartbeat failures), then we accept what
       // the client says. The same is the case with replica as well.
       // The OUT_OF_SERVICE from the client or replica needs to be confirmed as well since the service may be
       // currently in SERVICE

       /**
        * 同步实例是down或者starting的时候是可信的。因为只有在心跳失败时,客户端才会发送down或者starting
        *
        * 但是当实例的状态是UP 或者OUT_OF_SERVICE时。需要再次确认。
        */
       if ((!InstanceInfo.InstanceStatus.UP.equals(instanceInfo.getStatus()))
               && (!InstanceInfo.InstanceStatus.OUT_OF_SERVICE.equals(instanceInfo.getStatus()))) {
           logger.debug("Trusting the instance status {} from replica or instance for instance {}",
                   instanceInfo.getStatus(), instanceInfo.getId());
           return StatusOverrideResult.matchingStatus(instanceInfo.getStatus());
       }
       return StatusOverrideResult.NO_MATCH;
   }

   @Override
   public String toString() {
       return DownOrStartingRule.class.getName();
   }
}

3.3 单个对象

public class LeaseExistsRule implements InstanceStatusOverrideRule {

   private static final Logger logger = LoggerFactory.getLogger(LeaseExistsRule.class);

   @Override
   public StatusOverrideResult apply(InstanceInfo instanceInfo,
                                     Lease<InstanceInfo> existingLease,
                                     boolean isReplication) {
       // This is for backward compatibility until all applications have ASG
       // names, otherwise while starting up
       // the client status may override status replicated from other servers
       if (!isReplication) {
           InstanceInfo.InstanceStatus existingStatus = null;
           if (existingLease != null) {
               existingStatus = existingLease.getHolder().getStatus();
           }
           // Allow server to have its way when the status is UP or OUT_OF_SERVICE
           if ((existingStatus != null)
                   && (InstanceInfo.InstanceStatus.OUT_OF_SERVICE.equals(existingStatus)
                   || InstanceInfo.InstanceStatus.UP.equals(existingStatus))) {
               logger.debug("There is already an existing lease with status {}  for instance {}",
                       existingLease.getHolder().getStatus().name(),
                       existingLease.getHolder().getId());
               return StatusOverrideResult.matchingStatus(existingLease.getHolder().getStatus());
           }
       }
       return StatusOverrideResult.NO_MATCH;
   }

   @Override
   public String toString() {
       return LeaseExistsRule.class.getName();
   }
}

3.4 组合对象

/**
* This rule takes an ordered list of rules and returns the result of the first match or the
* result of the {@link AlwaysMatchInstanceStatusRule}.
*
* 这个规则包含一个有序的规则集合,如果有匹配的则返回第一个匹配的结果
* Created by Nikos Michalakis on 7/13/16.
*/
public class FirstMatchWinsCompositeRule implements InstanceStatusOverrideRule {

   /**实例匹配规则集合*/
   private final InstanceStatusOverrideRule[] rules;
   private final InstanceStatusOverrideRule defaultRule;
   private final String compositeRuleName;

   public FirstMatchWinsCompositeRule(InstanceStatusOverrideRule... rules) {
       this.rules = rules;
       this.defaultRule = new AlwaysMatchInstanceStatusRule();
       // Let's build up and "cache" the rule name to be used by toString();
       List<String> ruleNames = new ArrayList<>(rules.length+1);
       for (int i = 0; i < rules.length; ++i) {
           ruleNames.add(rules[i].toString());
       }
       ruleNames.add(defaultRule.toString());
       compositeRuleName = ruleNames.toString();
   }

   /**获取第一个匹配的状态*/
   @Override
   public StatusOverrideResult apply(InstanceInfo instanceInfo,
                                     Lease<InstanceInfo> existingLease,
                                     boolean isReplication) {
       for (int i = 0; i < this.rules.length; ++i) {
           StatusOverrideResult result = this.rules[i].apply(instanceInfo, existingLease, isReplication);
           if (result.matches()) {
               return result;
           }
       }
       return defaultRule.apply(instanceInfo, existingLease, isReplication);
   }

   @Override
   public String toString() {
       return this.compositeRuleName;
   }
}

猜你喜欢

转载自blog.csdn.net/ai_xiangjuan/article/details/80357959
今日推荐