具有组成和观察者模式的代码重复吗?

时间:2019-06-26 07:54:17

标签: java oop

假设我有两个带有下游订阅(订阅者)的类

class A {
   SubscriptionManager<A> subscriptionManager; // downstream subscriptions
   void addSub(Subscription<A> sub){
      subscriptionManager.addSub(sub);
   }
}

class B {
   SubscriptionManager<B> subscriptionManager; // downstream subscriptions
   void addSub(Subscription<B> sub){
      subscriptionManager.addSub(sub);
   }
}

这是我要处理的问题,也是设计问题。我已经多次听说过通过继承进行构图,在这样的示例中,我可以创建一个抽象类,其中包含订阅管理器并具有添加和删除订阅者的功能。

但是,compoisiton over inheritance使我不使用抽象类。我想知道这里正确的是什么?显然,您看到A, B类中的任何一个都与整个add方法存在代码重复(将来可能还会重复)。

2 个答案:

答案 0 :(得分:1)

您说对composition over inheritance是要牢记的重要原则,这是正确的;组合通常会更好,因为它可以为您提供更大的灵活性。

尽管如此,在我看来,抽象基类是合理的选择。考虑一下“是一个”问题:当一个类扩展到另一个类时,从子类到超类就会存在一个“是”关系。您的课程function loadRoute(json, map){ var markers = []; var dd = []; var color = []; var jsonParse = JSON.parse(json); var directionsDisplay = new google.maps.DirectionsRenderer; var directionsService = new google.maps.DirectionsService; for (var i = 0; i < jsonParse.length; i++){ var waypts = []; waypts.push({ location: pos, stopover: true }); var posorigin = new google.maps.LatLng(jsonParse[i].latitudemin, jsonParse[i].longitudemin); var posdestination = new google.maps.LatLng(jsonParse[i].latitude, jsonParse[i].longitude); var lastupdate = jsonParse[i].ultimaposizione; var content = jsonParse[i]; var icona = "https://img.icons8.com/color/administrator-male.png"; color[i] = jsonParse[i].color; var markernew = new google.maps.Marker({ position: new google.maps.LatLng(jsonParse[i].latitude, jsonParse[i].longitude), icon: icona, lastupdate: lastupdate, id: name, title: name, name: name, map: map }); markers.push(markernew); directionsService.route({ 'origin': parseFloat(jsonParse[i].latitudemin) + ',' + parseFloat(jsonParse[i].longitudemin), 'destination': parseFloat(jsonParse[i].latitude) + ',' + parseFloat(jsonParse[i].longitude), 'waypoints': waypts, 'optimizeWaypoints': true, 'travelMode': 'DRIVING' }, function(directions, status) { dd.push(new google.maps.DirectionsRenderer({ suppressInfoWindows: true, suppressMarkers: true, polylineOptions: { strokeOpacity: 0.7, strokeColor: color[dd.length] }, map: map, preserveViewport: true })); //dd.setMap(map); if (status == google.maps.DirectionsStatus.OK) { directionsDisplay = dd[dd.length - 1]; directionsDisplay.setDirections(directions); } } ); } var obj = { markers: markers, directions: directionsDisplay }; return obj; }; A都是您可以订阅的东西,因此B A

Subscribable
  

我想知道这里正确吗?

这些是设计选择,几乎没有一个客观上正确的选择-每个设计选择都有其优点和缺点。

某些OO编程语言支持mixins,它可以帮助您通过合成而不是继承来实现类似的功能,但是Java对此的支持不是很好。

答案 1 :(得分:0)

您的示例不违反DRY原理。您只是使用一个承诺处理订阅的对象。它周围的薄层不会重复任何知识,而是在正确委派。

您可以采用的另一种方法是使您的客户(A和B)成为将产生SubscriptionManager的具体工厂。这样,他们的客户就可以直接与管理器进行交互,而您不必编写包装方法。

class A {
   SubscriptionManager<A> subscriptionManager; // downstream subscriptions

   /**
    * There is some tension with Law of Demeter here,
    * but these are the decisions you have to make as a designer. 
    */
   SubscriptionManager<A> subManager() {
      //note: SubscriptionManager should be abstract to avoid tight coupling.
      return subscriptionManager;
   }
}