предисловие
Только лысина может стать сильнее
Оглядываясь назад на фронт:
В предыдущей статье уже объяснялся режим прокси, а сегодня я объясню его.орнаментЛа~
видяFilterInputStream
а такжеFilterOutputStream
Я видел то, что раньше слышалорнамент(Студенты, которые должны знать о IO, могут знать предложение: режим украшения наиболее часто используется в IO)!
На самом деле, будь то режим прокси или режим украшения. По сути, я думаю, что этоСпособ улучшения исходного объекта~
Тогда давайте начнем.Если в статье есть ошибки, пожалуйста, потерпите меня и поправьте меня в комментариях~
Отказ от ответственности: в этой статье используется JDK1.8.
1. Распространенные способы улучшения объекта
Много раз мы можемНедовольны объектами, которые дает нам Java, не удовлетворяет нашей функции. На данный момент мы хотим улучшить исходный объект Java, чтобы получить нужные нам функции~
Вообще говоря, есть три способа реализации улучшения объекта:
-
наследовать
- Наследовать родительский класс, расширить подкласс
-
Шаблон декоратора
- Используйте «обертки» для улучшения объектов
- прокси-режим
1.1 Наследование
Самый простой способ — наследовать родительский класс и расширить подкласс для достижения цели. Несмотря на простоту, этот способДефект очень большой:
- 1. ЕслиЕсли родительский класс имеет данные, информацию и атрибуты, то подкласс не может быть улучшен.
- Во-вторых, после реализации подклассаТребования не могут быть изменены, расширенный контентфиксированныйиз.
1.1.1 Первый пункт
Первая точкаВозьмите предыдущий раз, когда я изучал JDBC:
- В то время я хотел сам написать простой пул соединений JDBC, который состоит из
List<Connection>
справляться. Очевидно, что наш объект Connection, при записи вclose()
метод застрял. - Поскольку функция, которую мы хотим, это: вызов
close()
Это позволяет нашему соединению вернуться в «пул соединений» (коллекцию) вместо его закрытия. - В это время мыне можемУлучшение достигается за счет наследования от родительского класса. Поскольку объект Connection реализуется производителем базы данных, при получении объекта Connection связывается различная информация (имя пользователя, пароль базы данных, что представляет собой конкретная база данных и т. д.). насПодклассы, наследующие Connection, не могут получить соответствующие данные! не говоря уже о звонках
close()
метод.
1.1.2 Второй пункт
Второй моментТакже привожу пример:
Теперь я разрабатываю телефонный класс:
public class Phone {
// 可以打电话
public void call() {
System.out.println("打电话给周围的人关注公众号Java3y");
}
}
В этот момент я думаюПрослушайте рингтон перед звонком, поэтому я наследую класс Phone и реализую нужную функцию.
public class MusicPhone extends Phone {
// 听彩铃
public void listenMusic() {
System.out.println("我怀念的是无话不说,我怀念的是一起做梦~~~~~~");
}
@Override
public void call() {
// 在打电话之前听彩铃
listenMusic();
super.call();
}
}
Наша функция готова:
- В это время я вдруг хочу реализовать еще одно требование Я хочу сказать мне, какое сейчас время после прослушивания звонка. все в порядке, мыунаследовано для улучшенияодин раз:
// 这里继承的是MusicPhone类
public class GiveCurrentTimePhone extends MusicPhone {
// 给出当前的时间
public void currentTime() {
System.out.println("当前的时间是:" + System.currentTimeMillis());
}
@Override
public void call() {
super.call();
// 打完电话提示现在的时间是多少啦
currentTime();
}
}
Таким образом, мы все еще можем выполнить сброс задачи:
Но мне нужно сейчасхочу изменить сновасейчас:
- Я больше не хочу слушать CRBT, я просто хочу получать уведомления о времени после прослушивания телефона... (Но наш класс телефона времени уведомления наследуется от класса телефона для прослушивания CRBT), ,
- У меня есть другая возможность: я хочу сообщить время до прослушивания телефона, и слушать музыку после прослушивания телефона! ...
- еслиСпрос сильно колеблетсяслучай, и мы используемНаследование для достиженияЭто приведет к явлению:взрыв класса(всплеск количества занятий)! а такжеМожет быть много уровней наследования~
Итак, мы видим, что подкласс наследует родительский класс таким образом, чтобы расширитьочень ограниченный, негибкий~
Итак, у нас естьорнамент!
1.2 Декоративный режим
Во-первых, давайте посмотрим, как используется режим украшения.
1.2.1 Предварительный код
Телефонный интерфейс:
// 一个良好的设计是抽取成接口或者抽象类的
public interface Phone {
// 可以打电话
void call();
}
конкретная реализация:
public class IphoneX implements Phone {
@Override
public void call() {
System.out.println("打电话给周围的人关注公众号Java3y");
}
}
1.2.2 Реализация режима упаковки
выше у нас естьИмеет интерфейс и реализацию по умолчанию. Схема упаковки делается так:
Сначала мы получаем одиндекоратор, который реализует интерфейс длякомбинацияполучить нашКласс реализации по умолчанию.
// 装饰器,实现接口
public abstract class PhoneDecorate implements Phone {
// 以组合的方式来获取默认实现类
private Phone phone;
public PhoneDecorate(Phone phone) {
this.phone = phone;
}
@Override
public void call() {
phone.call();
}
}
С декоратором наше расширение можетРасширение с помощью декораторов, наследовать декоратор, чтобы расшириться просто отлично!
мы хотимслушать музыку перед звонком:
// 继承着装饰器来扩展
public class MusicPhone extends PhoneDecorate {
public MusicPhone(Phone phone) {
super(phone);
}
// 定义想要扩展的功能
public void listenMusic() {
System.out.println("继续跑 带着赤子的骄傲,生命的闪耀不坚持到底怎能看到,与其苟延残喘不如纵情燃烧");
}
// 重写打电话的方法
@Override
public void call() {
// 在打电话之前听音乐
listenMusic();
super.call();
}
}
Теперь я тоже хочу бытьУведомление о текущем времени после совершения звонка, так и мыНаследовать класс декоратора для расширения:
// 这里继承的是MusicPhone装饰器类
public class GiveCurrentTimePhone extends PhoneDecorate {
public GiveCurrentTimePhone(Phone phone) {
super(phone);
}
// 自定义想要实现的功能:给出当前的时间
public void currentTime() {
System.out.println("当前的时间是:" + System.currentTimeMillis());
}
// 重写要增强的方法
@Override
public void call() {
super.call();
// 打完电话后通知一下当前时间
currentTime();
}
}
Задания можно выполнить:
СразуВ настоящее времяТаким образом, это более хлопотно, чем прямое наследование родительского класса, и функциональный эффект тот же.... Давайте продолжим смотреть вниз~~
На данный момент я не хочу слышать CRBT перед звонком, это очень просто: мыне украшенЭто просто прекрасно!
На данный момент я хочу сообщить время до звонка и прослушать CRBT после звонка.
- Примечание. Несмотря на то, что говорится об изменении кода в классе,ноЭто изменение разумно. потому что я определяю
GiveCurrentTimePhone类
а такжеMusicPhone类
сам по себе семантическиникаких правилПорядок выполнения расширенных функций - Наследование отличается: сначала наследуйте Phone-> реализуйте MusicPhone->, а затем наследуйте MusicPhone, чтобы реализовать GiveCurrentTimePhone. Этофиксированный, он был логически унаследован отмертво написаноКонкретный кодтрудно изменитьиз.
Таким образом, мы все еще можем выполнить функцию очень просто:
2. Объяснение режима украшения
Прочитав приведенный выше код, некоторые учащиеся могут все еще не понимать, как режим украшения реализует «украшение». Позвольте мне еще раз проанализировать:
- Шаг 1: У нас есть интерфейс телефона, который определяет функциональность телефона.
- Шаг 2: У нас есть простейшая реализация класса iPhoneX
- Шаг 3: Напишите абстрактный класс декоратора PhoneDecorate длякомбинация(Конструктор передан) способ получить нашу простейшую реализацию класса iPhoneX. На самом деле роль абстрактного класса декоратора такова.играет роль(Основную функцию по-прежнему выполняет простейший класс реализации iPhoneX, но врасширятькогда ты можешьДобавьте некоторые функции, которых нет).
- Шаг 4: Если вы хотите расширить функцию, наследуйте абстрактный класс декоратора PhoneDecorate, передайте объект, который вы хотите улучшить (класс простейшей реализации iPhoneX или объект, который был улучшен), и завершите наше расширение!
Взгляните на картинку ниже, и вы все поймете!
Часто наш код можно опустить и он выглядит так (Это очень похоже на IO?! )
// 先增强听音乐的功能,再增强通知时间的功能
Phone phone = new GiveCurrentTimePhone(new MusicPhone(new IphoneX()));
Результат тот же:
2.1 Преимущества и недостатки режима украшения
преимущество:
- Декоративно-декорированные классы могут бытьНезависимость, низкое сцепление. Им не обязательно знать о существовании друг друга
- Орнамент – это своего рода наследствоальтернативастроить планы,Независимо от того, сколько слоев обернуто, возвращаемый объект является отношением.(Пример выше: пакет по-прежнему относится к типу «Телефон»).
- Для достижения динамического расширения, покаУнаследовал декоратормогудинамичныйРасширить желаемый функционал.
недостаток:
- Многослойная отделка более сложная, что увеличивает сложность системы. Нам нехорошо заниматься отладкой~
3. Резюме
Наконец, давайте добавим диаграммы классов режима упаковки и режима прокси:
Три способа улучшения объекта:
- наследовать
- режим упаковки
- прокси-режим
Поэтому, пока API, предоставляемого нам Java, недостаточно, мы можем его улучшить. При написании кода какой-то класс прописывается насмерть, а функции мало, только доработать!
Разберитесь с режимом упаковки, а затем начните путь ввода-вывода~~~
Использованная литература:
- Дзен шаблонов проектирования
- Wangjingxin.top/2016/10/21/…
Если в статье есть ошибки, пожалуйста, исправьте меня и поделитесь друг с другом. Учащиеся, привыкшие читать технические статьи в WeChat и желающие получить больше ресурсов по Java, могутОбратите внимание на публичный аккаунт WeChat: Java3y.
Оглавление Навигация по статьям: