В развитии бизнес-отдела большинство различных потребностей бизнеса мы дополняем и предоставляем решения, во многих сценариях мы можем решить проблему с помощью CRUD, но такая работа не сильно улучшает технический персонал, как Освободите себя от бизнеса и найдите радость в написании кода Я предпринял несколько попыток, и использование шаблонов проектирования для улучшения моего бизнес-кода — одна из них. Сделайте свой код более лаконичным и надежным и найдите в нем радость.
предисловие
В Али много замечательных людей.У всех у них есть общая черта, то есть способность думать о проблемах.Больше всего я восхищаюсь людьми с сильными мыслительными способностями, людьми, которые имеют глубокое понимание и взгляды на вещи, большинство людей все еще остаются на поверхности. Глядя на проблему, многие люди заключены в тюрьму в уме и не могут убежать. Древние говорили, что три бессмертных должны сделать добродетель, сделать заявление и внести вклад. Сделать заявление - это способность мышления и познания, по сути, и есть различие между познанием и мышлением. Поэтому после удаления утомительной работы, как найти радость в коде за ограниченное время, что нужно улучшить, так это способность думать и планировать.Организовал 562-страничный PDF-документ шаблона проектирования.
Шаблон проектирования цепочки ответственности
▐ определение схемы
Шаблон цепочки ответственности — это один из шаблонов поведенческого проектирования. Эта модельная структура чем-то похожа на железную цепь в реальной жизни, которая состоит из железных колец, соединенных конец к концу, чтобы сформировать цепь.Если эта структура используется в области программирования, каждый узел можно рассматривать как объект, а каждый объект имеет различную логику обработки, запрос отправляется с головного конца цепочки, и каждый объект узла проходит по пути цепочки по очереди, пока не будет объекта для обработки запроса.Такой паттерн мы называем цепочкой модели ответственности.
▐ Применимые сценарии
Он подходит для обработки процессов с несколькими узлами, каждый узел выполняет свою часть, и узлы не знают о существовании друг друга, например, поток утверждения OA и механизм фильтра в веб-разработке Java.
-
Несколько объектов могут обрабатывать один и тот же запрос, но какой объект обрабатывает запрос, динамически определяется во время выполнения.
-
Отправляет запрос одному из этих объектов, не зная обработчика запроса.
-
Набор объектов должен обрабатываться динамически для обработки запросов.
Приведу пример из жизни, например, вам вдруг кажется, что мир такой большой и вы хотите его увидеть, а на самом деле вы не можете потерять работу, и вы получаете ОА заявление на отпуск. количество дней отпуска от полдня до 1 дня, может быть утверждено непосредственным руководителем и все, если это отпуск от 1 до 3 дней, то необходимо согласование с заведующим отделением, если от 3 до 30 дней, он должен быть одобрен генеральным директором; если он составляет более 30 дней, он не будет утвержден в обычном порядке. Этот простой процесс можно попробовать в нашем текущем бизнес-сценарии.
▐ Практический опыт
Бизнес-процесс прост:
-
звонок, чтобы отменить кредитную карту
-
Персонал аннулирует кредитную карту
Предыстория аннулирования кредитной карты следующая.Если на кредитной карте есть неоплаченные счета, перерасходы и специальные годовые сборы, которые не используются, аннулировать кредитную карту не разрешается.В связи с этим мы добавили набор того, разрешать ли отмену перед отменой.проверка логики.
Примерно следующим образом:
-
Если счет не возвращен, например, нет выписки, нет выписки, нет выписки и не уплачивается ежегодная плата за управление.
-
Есть ли лишние деньги в переливе.
-
Есть ли большое количество неиспользованных баллов, пользователю необходимо подтвердить отказ от баллов и т. д.
Для таких ситуаций установлены три типа фильтров, а именно:
-
UserLogoutUnpaidBillsLimitFilter: есть ли непогашенная сумма.
-
UserLogoutOverflowLimitFilter: есть ли переполнение.
-
UserLogoutGiveUpPointsLimitFilter: отказываться ли от больших сумм.
Логика - это первое решение по USERLOGOUTUNPAIDBILLSLIMITFILTER Определите, может ли текущий пользователь выйти из системы кредитных карт. Если разрешено продолжить пользовательLogOutoverFlowliMitFilter, чтобы определить, есть ли разрез переполнения, будь то кредитная карта с отписанием; если нет денег, чтобы продолжать переполнить из пользователя userLogOutgiveupPointSlimitFilter, определите, есть ли текущий пользователь высоких точек, перед Три судьи, до тех пор, пока человек не соответствует возврату заранее.
public boolean canLogout(String userId) {
//获取用户信息
UserInfo userInfo = getUserInfo(userId);
// 构造注销信用卡限制过滤器链条
LogoutLimitFilterChain filterChain = new LogoutLimitFilterChain();
filterChain.addFilter(new UserLogoutUnpaidBillsLimitFilter());
filterChain.addFilter(new UserLogoutOverflowLimitFilter());
filterChain.addFilter(new UserLogoutGiveUpPointsLimitFilter());
boolean checkResult = filterChain.doFilter(filterChain, userInfo);
//filterChain.doFilter方法
public boolean doFilter (LogoutLimitFilterChain filterChain, UserInfo userInfo){
//迭代调用过滤器
if (index < filters.size()) {
return filters.get(index++).doFilter(filterChain, userInfo);
}
}
}
//UserLogoutUnpaidBillsLimitFilter.doFilter方法
public boolean doFilter(LogoutLimitFilterChain filterChain, UserInfo userInfo) {
//获取用户当前欠款金额
UserCardBillInfo userCardBillInfo = findUserCardBillInfo(userInfo);
// 判断当前卡用户是否允许消费
if (userCardBillInfo != null) {
if ((!CAN_LOGOUT.equals(userCardBillInfo.getEnabledLogout()))) {
return false;
}
}
//其余情况,继续往后传递
return filterChain.doFilter(filterChain, memberInfo, consumeConfig);
}
//UserLogoutOverflowLimitFilter.doFilter方法
public boolean doFilter(LogoutLimitFilterChain filterChain, UserInfo userInfo) {
//判断用户是否存在溢出款
UserCardDeposit userCardDeposit = findUserCardDeposit(userInfo);
// 判断当前卡用户是否允许消费
if (userCardDeposit != null) {
if (userCardDeposit.getDeposit() != 0) {
return false;
}
}
//其余情况,继续往后传递
return filterChain.doFilter(filterChain, memberInfo, consumeConfig);
}
Резюме: Логика оценки каждого условия ограничения заключена в специальный фильтр. Если логика определенного условия ограничения изменена, это не повлияет на другие условия. Если вам нужно добавить новое условие ограничения, вам нужно только восстановить Фильтровать и вплетать в FilterChain.
Объект-обработчик в цепочке ответственности имеет только два поведения: одно — обрабатывать запрос, а другое — пересылать запрос следующему узлу.Объекту-обработчику не разрешено пересылать запрос предыдущему узлу после обработки запрос состояние. Для цепочки ответственности есть только два случая для запроса в конце.Один состоит в том, что он обрабатывается обрабатывающим объектом, а другой - что все объекты не обрабатываются.Первый случай называет цепочку ответственности чистым цепочка ответственности.Последний случай называется нечистой цепочкой ответственности.В практических приложениях это в основном нечистая цепочка ответственности.Организовал 562-страничный PDF-документ шаблона проектирования.
Шаблоны разработки стратегии
▐ Определение схемы
Как следует понимать слово стратегия?Например, когда мы выходим из дома, мы выбираем разные способы передвижения, такие как велосипед, автобус, поезд, самолет и т. д. Каждый из этих способов передвижения является стратегией.
Другой пример, когда мы идем в торговый центр.Торговый центр в настоящее время занимается мероприятиями, в том числе скидками, полными скидками, скидками и т. д. На самом деле, как бы торговый центр не проводил акции, в конечном счете, есть некоторые алгоритмы.Сами эти алгоритмы являются всего лишь стратегиями.И эти алгоритмы могут быть заменены друг другом в любой момент.Например, для одного и того же товара скидка 20% сегодня, скидка 30% завтра когда будет больше 100, эти стратегии взаимозаменяемы.
Шаблон стратегии определяет набор алгоритмов, инкапсулирует каждый алгоритм и делает их взаимозаменяемыми.
▐ Применимые сценарии
Основная цель состоит в том, чтобы исключить большое количество кодов if else и извлечь логику алгоритма, стоящую за каждым суждением, в конкретный объект стратегии.Когда логика алгоритма изменена, пользователь не имеет никакого восприятия, и ему нужно только изменить внутреннюю логику объект стратегии. Такие объекты стратегии обычно реализуют общий интерфейс и могут достигать цели обмена.
-
Сценарии, в которых несколько классов имеют лишь немного отличающиеся алгоритмы или поведение.
-
Сценарии, в которых алгоритм должен свободно переключаться
-
Сценарии, требующие маскировки правил алгоритма
▐ Практический опыт
Бизнес-процесс прост:
-
Выберите элемент
-
Выберите другой метод скидки для оформления заказа
Например, на предстоящем мероприятии Double Eleven некоторые офлайн-продавцы проведут мероприятия. Скидки следующие: 300–80 %, некоторые товары со скидкой 50 %, а в зависимости от уровня членства могут быть предоставлены разные скидки. Не менее 30 скидка %, на юбилейные мероприятия скидка 20% и т. д. Если эти скидки за активность не распределяются, то как реализовать и рассмотреть режим стратегии масштабируемости — хороший выбор.
/**
* 抽象折扣策略接口
*/
public abstract class DiscountStrategy {
/**
* 计算折扣后的价格
* @param price 原价
* @return 折扣后的价格
*/
public abstract CalculationResult getDiscountPrice(Long userId ,BigDecimal price);
}
/**
* 满减活动 -- 满300减80
*/
public class FullReductionStrategyOne extends DiscountStrategy {
/**
* 计算折扣后的价格
* @param price 原价
* @return
*/
@Override
public CalculationResult getDiscountPrice(Long userId ,BigDecimal price) {
if (price.doubleValue() < 300) {
return price;
}
BigDecimal dealPrice= price.subtract(BigDecimal.valueOf(80));
return getCalculationResult(userId,dealPrice);
}
}
/**
* 部分商品5折
*/
public class MerchandiseDiscountStrategy extends DiscountStrategy {
/**
* 计算折扣后的价格
* @param price 原价
* @return
*/
@Override
public CalculationResult getDiscountPrice(BigDecimal price) {
BigDecimal dealPrice= price.multiply(BigDecimal.valueOf(0.5));
return getCalculationResult(userId,dealPrice);
}
}
/**
*当有新的需求式,我们只需要添加一个新的接口即可,不需要修改原有的具体策略实现代码即可完成。
*定义完策略后,我们再定义一个”环境角色”,假设我们这个环境角色就使用价格对象吧
*/
public class Price {
private DiscountStrategy discountStrategy;
/**
* 定义一个无参构造,用于实例对象
*/
private Price(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
/**
* 获取折扣后的价格
*
* @param price 原始价格
* @return
*/
public CalculationResult discount(Long userId,BigDecimal price) {
return discountStrategy.getDiscountPrice(userId ,price);
}
}
Паттерн стратегии — это поведенческий паттерн, который отделяет использование алгоритма от самого алгоритма и делегирует управление другим объектам. Классы реализации стратегии, как правило, представляют собой инкапсулированные облегченные алгоритмы, когда клиент (вызывающий) сталкивается с разными ситуациями, эти алгоритмы могут динамически заменяться друг другом по мере необходимости. Выбор стратегии полностью осуществляется клиентом, что требует от клиента понимания всех классов реализации стратегии.Хотя гибкость системы повышается, это также увеличивает сложность использования клиентом. Паттерн стратегии воплощает в себе принцип «открыто-закрыто» — «открыто для расширения, закрыто для модификации». Когда добавляется новая стратегия, она не влияет на модификацию других классов, повышает расширяемость и открыта для расширения, зависит только от абстракции, а не от конкретной реализации, поэтому модификация закрыта. Это уменьшает связанность, улучшая масштабируемость кода.
Резюме: Push-логика каждого канала инкапсулирована в определенную стратегию, и изменение одних политик не повлияет на другие политики.Поскольку реализован общий интерфейс, политики можно заменять друг другом, а пользователю удобно. Например, задача, отклоняющая стратегию в Java Threadpoolexecutor.Когда пул потоков уже насыщен, выполняется политика отклонения, и конкретная логика отклонения инкапсулируется в REJECTEDExecution RejectedExecutionHandler.
Шаблон дизайн шаблона
▐ Определение схемы
Ценность шаблона заключается в определении скелета.Определен процесс обработки проблемы внутри скелета.Общая логика обработки, как правило, реализуется родительским классом, а персонализированная логика обработки реализуется подклассом.
Например, жареный тертый картофель и жареный мапо тофу, общая логика такова:
1. Измельчение овощей
2. Слить масло
3. Обжарить
4. Из горшка
1, 2 и 4 похожи, но отличается шаг 3. Чтобы поджарить тертый картофель, вам нужно обжаривать лопатой, но вы должны толкать тофу ложкой, иначе тофу будет гнилым.
▐ Сценарии использования
Для потока обработки различных сценариев часть логики является общей и может быть размещена в родительском классе как общая реализация, а часть логики персонализирована и должна быть реализована подклассами.
В шаблоне шаблона абстрактный класс предоставляет способ/шаблон, который определяет его методы. Его подклассы могут при необходимости переопределить реализацию метода, но вызовы будут выполняться так, как определено в абстрактном классе. Этот тип шаблона проектирования является поведенческим шаблоном.
▐ Практический опыт
Следуя предыдущему примеру со скидками на товары, позже мы добавили два новых требования:
-
Пользователи пользуются различными скидками на добавление следов.
-
Следует ли повышать уровень членства после того, как пользователь воспользуется скидкой.
Итак, теперь поток становится таким:
1. Запускается трассировка.
2. Рассчитайте различные скидки для пользователей.
3. Разрешено ли повышать уровень членства, разрешено ли выполнять логику повышения уровня членства.
4. Трассировка заканчивается.
Среди них общие 1 и 4, а персонализированные 2 и 3. Ввиду этого перед стратегией скидок может быть добавлен слой стратегии родительского класса, а общая логика размещена в родительском классе.
Модифицированный код выглядит следующим образом:
abstract class AbstractDiscountStrategy implements DiscountStrategy{
@Override
public CalculationResult getDiscountPrice(Long userId ,BigDecimal price) {
//1.构造span
Span span = buildSpan();
//2.具体通道推送逻辑由子类实现
CalculationResult calculationResult =getCalculationResult(userId,price);
//3.是否允许升级会员等级,如果允许执行升级逻辑
if(!calculationResult.isSuccess() && canUpgrade()){
upgradeLevel(userId,calculationResult);
}
//4.trace结束
span.finish();
return calculationResult;
}
//具体推送逻辑由子类实现
protected abstract CalculationResult getCalculationResult(Long userId,BigDecimal price) ;
//是否允许升级会员等级由子类实现
protected abstract boolean canUpgrade(Long userId,CallResult callResult);
}
/**
* 满减活动 -- 满300减80
*/
public class FullReductionStrategyOne extends AbstractDiscountStrategy {
@Override
protectedCalculationResult getCalculationResult(Long userId,BigDecimal price){
//执行折扣逻辑
}
@Override
protected boolean canUpgrade(Long userId,CallResult callResult){
return false
}
}
Шаблон проектирования наблюдателя
▐ Определение схемы
Во время аукциона аукционист наблюдает за самой высокой ставкой, а затем уведомляет других участников торгов о ставках.Этот режим может использовать режим наблюдателя. Как следует из названия, для этого шаблона требуются две роли: Observer и Observable. Когда состояние Observable изменится, наблюдатель будет уведомлен, и наблюдатель, как правило, реализует общий интерфейс.
Например, в java.util.Observer, когда Observable необходимо уведомить Observer, он может вызывать метод update Observer один за другим.Успех обработки Observer не должен влиять на процесс Observable.
▐ Сценарии использования
Когда между объектами существует отношение «один ко многим», используется шаблон наблюдателя. Например, при изменении объекта автоматически уведомляются объекты, зависящие от него. Паттерн Наблюдатель — это поведенческий паттерн.
Изменение состояния объекта (Observable) должно уведомлять другие объекты, существование Observer не влияет на результаты обработки Observable, а добавление или удаление Observer не знает о Observable.
Например, в подписке на сообщения Кафки Производитель отправляет сообщение в Тему, а на то, подписаны ли на Тему один или 10 Потребителей, Производителю не нужно обращать внимание.
▐ Практический опыт
В режиме проектирования цепочки ответственности я решил проблему отмены проверки лимита кредитной карты через три фильтра, один из которых используется для проверки баллов пользователя, здесь я просто читаю общее количество баллов пользователя и количество раз, затем количество потребления принесет баллы Как происходит накопление?
На самом деле при накоплении используется режим наблюдателя, в частности, когда транзакционная система получает обратный вызов об успешном платеже, она публикует «событие об успешном платеже» через механизм событий Spring.
Таким образом, абоненты, ответственные за накопление количества потребляемых баллов и ответственные за голосовую трансляцию, получат «событие успешного платежа», а затем выполнят свою собственную бизнес-логику.
Нарисуйте простую схему, чтобы описать:
/**
支付回调处理者
*/
PayCallBackController implements ApplicationContextAware {
private ApplicationContext applicationContext;
//如果想获取applicationContext需要实现ApplicationContextAware接口,Spring容器会回调setApplicationContext方法将applicationContext注入进来
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
@RequestMapping(value = "/pay/callback.do")
public View callback(HttpServletRequest request){
if(paySuccess(request){
//构造支付成功事件
PaySuccessEvent event = buildPaySuccessEvent(...);
//通过applicationContext发布事件,从而达到通知观察者的目的
this.applicationContext.publishEvent(event);
}
}
}
/**
* 语音播报处理者
*
*/
public class VoiceBroadcastHandler implements ApplicationListener<PaySuccessEvent>{
@Override
public void onApplicationEvent(PaySuccessEvent event) {
//语音播报逻辑
}
}
//其他处理者的逻辑类似
Резюме: Паттерн наблюдатель разделяет наблюдаемое и наблюдателя, и существование наблюдателя не повлияет на существующую логику наблюдаемого.
Шаблон оформления декоратора
▐ Определение схемы
Шаблон декоратора позволяет добавлять новые функции к существующему объекту без изменения его структуры. Этот тип шаблона проектирования представляет собой структурный шаблон, который действует как оболочка существующего класса. Этот шаблон создает оформленный класс, который является оболочкой исходного класса и предоставляет дополнительные функции, сохраняя при этом целостность сигнатур методов класса.
Декоратор используется для обертывания исходного класса и расширения функции прозрачно для пользователя.Например, BufferedInputStream в Java может улучшить обертку InputStream, чтобы обеспечить функцию буферизации.
▐ Сценарии использования
Добавляйте обязанности к отдельным объектам динамично и прозрачно, не затрагивая другие объекты. Функции должны добавляться к объекту динамически, и эти функции также могут быть динамически удалены. Когда система не может быть расширена или унаследована посредством наследования. Если вы хотите улучшить функции исходного класса, но не хотите добавлять слишком много подклассов, вы можете использовать шаблон декоратора для достижения того же эффекта.
▐ Практический опыт
Есть кофейня, в которой продаются все виды кофе, латте, капучино, кофе Блю Маунтин и т. д. Перед завариванием клиентов спросят, хотят ли они добавить сахар, молоко, мяту и т. д. Таким образом, разные сорта кофе с разными приправами будут продаваться по разным ценам.
/**
* 抽象类Coffee
*/
public abstract class Coffee {
/**
* 获取咖啡得名字
*/
public abstract String getName();
/**
* 获取咖啡的价格
*/
public abstract double getPrice();
}
/**
*利用继承和组合的结合,现在我们可以考虑设计出一个装饰类,它也继承自coffee,
*并且它内部有一个coffee的实例对象
*/
public abstract class CoffeeDecorator implements Coffee {
private Coffee delegate;
public CoffeeDecorator(Coffee coffee) {
this.delegate = coffee;
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public double getPrice() {
return delegate.getPrice();
}
}
/**
*牛奶咖啡的装饰者模式的案例
*/
public class MilkCoffeeDecorator extends CoffeeDecorator {
public MilkCoffeeDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getName() {
return "牛奶, " + super.getName();
}
@Override
public double getPrice() {
return 1.1 + super.getPrice();
}
}
//其他咖啡的模式类似
/**
*测试案例 可以通过加入不用内容 咖啡名称和价格都是不同的
*/
public class App {
public static void main(String[] args) {
// 得到一杯原始的蓝山咖啡
Coffee blueCoffee = new BlueCoffee();
System.out.println(blueCoffee.getName() + ": " + blueCoffee.getPrice());
// 加入牛奶
blueCoffee = new MilkCoffeeDecorator(blueCoffee);
System.out.println(blueCoffee.getName() + ": " + blueCoffee.getPrice());
// 再加入薄荷
blueCoffee = new MintCoffeeDecorator(blueCoffee);
System.out.println(blueCoffee.getName() + ": " + blueCoffee.getPrice());
// 再加入糖
blueCoffee = new SugarCoffeeDecorator(blueCoffee);
System.out.println(blueCoffee.getName() + ": " + blueCoffee.getPrice());
}
}
Резюме: Используя шаблон декоратора для улучшения функции, пользователю нужно всего лишь выполнить простую комбинацию, чтобы продолжить использовать исходную функцию. Шаблон декоратора полностью демонстрирует гибкость композиции. Используйте его для расширений. Это также воплощение принципа открытого-закрытого. Если функция времени выполнения динамически расширяется относительно класса. В это время вы можете рассмотреть возможность использования шаблона декоратора!
Шаблон проектирования моста
▐ Определение схемы
Шаблон моста — это структурный шаблон проектирования, который может разделить большой класс или ряд тесно связанных классов на две независимые иерархии абстракции и реализации, которые можно использовать отдельно во время разработки.
Мост используется для отделения абстракции от реализации, чтобы они могли меняться независимо друг от друга. Этот тип шаблона проектирования является структурным шаблоном, который разделяет абстракцию и реализацию, обеспечивая структуру моста между ними.
▐ Сценарии использования
Если системе необходимо добавить больше гибкости между абстрактными классами и конкретными классами и избежать установления отношений статического наследования между двумя уровнями, шаблон моста может заставить их установить отношения ассоциации на абстрактном уровне.
Абстрактная часть и часть реализации могут быть независимо расширены путем наследования, не влияя друг на друга.Когда программа работает, объект подкласса абстрактного класса и объект подкласса класса реализации могут быть динамически объединены, и система должна понимать роль абстрактного класса Динамическая связь с реализацией ролей класса.
Класс имеет два (или более) измерения, которые изменяются независимо друг от друга, и оба (или более) измерения необходимо расширять независимо.
Режим моста особенно подходит для тех систем, которые не хотят использовать наследование или имеют резкое увеличение количества систем из-за множественного наследования.
▐ Практический опыт
В системе управления производительностью после создания данных они должны пройти через три процесса сбора, агрегирования и хранения, прежде чем пользователи смогут запрашивать их. Сбор может быть сбором snmp или сбором ems; агрегирование может быть агрегированием storm или агрегированием spark; хранилищем может быть хранилище hdfs или хранилище mpdb. Для разных сценариев мы можем гибко выбирать разные методы сбора, агрегации и хранения. Такого рода функции должны поддерживаться несколькими службами, и каждая служба имеет разные типы реализации.Подходит режим моста.
Режим моста, как следует из названия, рассматривает каждую службу как мост, и мы можем выбирать разные мосты в соответствии с реальной сценой. В приведенном выше примере показано, что перед использованием данных необходимо пройти через три моста: Мост сбора -> Мост агрегации -> Мост входящего трафика. Каждый мост может выбрать другую конфигурацию.Организовал 562-страничный PDF-документ шаблона проектирования.
/**
*
* 采集桥采集服务
*
*/
public abstract class CollectionService
{
abstract void execute();
public void run()
{
execute();
}
}
/**
* 汇聚桥 汇聚服务
*
*/
public abstract class AggregationService
{
public void run()
{
if(null != collectionService)
{
collectionService.run();
}
execute();
}
abstract void execute();
CollectionService collectionService;
public AggregationService(CollectionService collectionService)
{
this.collectionService = collectionService;
}
}
/**
*
* 入库桥 入库服务
*
*/
public abstract class StoreService
{
public void run()
{
if(null != aggregationService)
{
aggregationService.run();
}
execute();
}
abstract void execute();
AggregationService aggregationService;
public StoreService(AggregationService aggregationService)
{
this.aggregationService = aggregationService;
}
}
/**
*
* EMS采集桥
*
*/
public class EMSCollectionService extends CollectionService
{
@Override
void execute()
{
System.out.println("EMS collection.");
}
}
/**
*
* SNMP采集桥
*
*/
public class SNMPCollectionService extends CollectionService
{
@Override
void execute()
{
System.out.println("SNMP collection.");
}
}
/**
*
* Storm汇聚桥
*
*/
public class StormAggregationService extends AggregationService
{
public StormAggregationService(CollectionService collectionService)
{
super(collectionService);
}
@Override
void execute()
{
System.out.println("Storm aggregation.");
}
}
/**
*
* Spark汇聚桥
*
*/
public class SparkAggregationService extends AggregationService
{
public SparkAggregationService(CollectionService collectionService)
{
super(collectionService);
}
@Override
void execute()
{
System.out.println("Spark aggregation.");
}
}
/**
*
* MPPDB汇聚桥
*
*/
public class MPPDBStoreService extends StoreService
{
public MPPDBStoreService(AggregationService aggregationService)
{
super(aggregationService);
}
@Override
void execute()
{
System.out.println("MPPDB store.");
}
}
/**
*
* HDFS汇聚桥
*
*/
public class HDFSStoreService extends StoreService
{
public HDFSStoreService(AggregationService aggregationService)
{
super(aggregationService);
}
@Override
void execute()
{
System.out.println("HDFS store.");
}
}
/**
*
* 类功能说明: 桥接模式测试
*/
public class BridgeTest
{
public static void main(String[] args)
{
CollectionService snmpService = new SNMPCollectionService();
AggregationService stormService = new StormAggregationService(snmpService);
StoreService hdfsService = new HDFSStoreService(stormService);
hdfsService.run();
}
}
Резюме: Мостовой режим может отделить стабильную и расширяемую части системы, упрощая расширение системы, удовлетворяя принципу OCP и закрывая модификацию вызывающей стороны.
**Автор: сотрудник отдела технологий Alibaba Tao.
**no.OSCHINA.net/U/4662964/no…