предисловие
Цель этой статьи - быстро разобраться в часто используемых шаблонах проектирования и понять, на какие ситуации в основном нацелен каждый шаблон, и его основные характеристики.Перед каждым шаблоном для читателей перечислены одна или несколько справочных страниц, которые можно прочитать подробно. разобраться в деталях.
Делится на три статьи:
- Часть 1. Основные концепции шаблонов проектирования и творческих шаблонов проектирования
- Часть 2: Шаблоны поведенческого проектирования
- Далее: Шаблоны структурного проектирования
быстрый отзыв
структурный
- Адаптер
- Декоратор
- Прокси-режим (Прокси)
- Внешний вид/Фасадный режим (Фасад)
- Шаблон моста
- Композитный режим
- Наилегчайший вес
идея
Прежде всего, дайте понять, что шаблоны проектирования — это не высокотехнологичные и не извращенные трюки. Шаблон проектирования — это всего лишь дизайнерская идея.Для разных бизнес-сценариев структура кода разрабатывается по-разному.Его важнейшее назначение — разъединить, по расширению,а также для масштабируемости и надежности, но это все основано на развязке.
Высокая сплоченность и низкая связанность
высокая сплоченность: В системе взаимодействуют два модуля А и В. Если модификация модуля А не влияет на работу модуля В, считается, что А имеет достаточную связность.
низкое сцепление: То есть между модулем А и модулем В существует зависимость, то при изменении В модуль А может еще нормально работать, тогда А и В считаются малосвязанными.
структурный
Адаптер
у-у-у. Краткое описание.com/afraid/93821721No…
определение
Когда клиентский класс вызывает метод адаптера, метод класса адаптера будет вызываться внутри класса адаптера, и этот процесс прозрачен для клиентского класса, а клиентский класс не имеет прямого доступа к классу адаптера. Поэтому адаптеры могут заставить классы, которые не могут взаимодействовать из-за несовместимых интерфейсов, работать вместе. Это мотивация шаблона адаптера.
Роль
-
Целевая роль: это ожидаемый интерфейс. Примечание. Поскольку здесь обсуждается шаблон адаптера класса, цель не может быть классом.
-
Роль источника (Adapee): интерфейс, который необходимо адаптировать сейчас.
-
Роль адаптера (Adaper): класс адаптера является ядром этого шаблона. Адаптер преобразует исходный интерфейс в целевой интерфейс. Очевидно, что эта роль не может быть интерфейсом, а должна быть конкретным классом.
адаптер класса
Создайте новый класс, наследуйте исходный класс и реализуйте новый интерфейс.
class adapter extends oldClass implements newFunc{}
объектный адаптер
Создайте новый класс, который содержит экземпляр исходного класса и реализует новый интерфейс.
class adapter implements newFunc { private oldClass oldInstance ;}
-
Адаптеры классов используют наследование объектов, которое определено статически.
-
Способ, которым адаптер объекта использует композицию объектов, — это способ динамической композиции.
адаптер интерфейса
Создайте новый абстрактный класс, реализующий старые методы интерфейса
abstract class adapter implements oldClassFunc { void newFunc();}
Суммировать
Рекомендуется максимально использовать реализацию объектных адаптеров, используя больше синтеза/агрегации и меньше наследования.. Конечно, конкретная проблема подробно анализируется, и метод реализации выбирается в соответствии с потребностями, и наиболее подходящий является лучшим.
преимущество
- лучшее повторное использование
- лучшая масштабируемость
недостаток
Чрезмерное использование адаптеров сделает систему очень грязной и трудной для понимания в целом.. Например, очевидно, что вызывается интерфейс А, но на самом деле он адаптирован к реализации интерфейса Б. Если таких ситуаций в системе слишком много, это равносильно катастрофе.Поэтому, если в этом нет необходимости, можно напрямую рефакторить систему без использования адаптера.
Декоратор
Добавьте новые функции к классу объектов, и способ декорирования не имеет ничего общего с конкретной внутренней логикой.
выполнить
Разрабатывайте различные виды напитков, в напитки можно добавлять ингредиенты, например молоко, и поддерживать динамическое добавление новых ингредиентов. Для каждого дополнительного ингредиента цена этого напитка увеличивается, что требует расчета цены напитка.
На изображении ниже показано добавление нового ингредиента Mocha в напиток DarkRoast, за которым следует добавление ингредиента Whip. DarkRoast обёрнут Mocha, а Mocha обернут Whip. Все они наследуются от одного и того же родительского класса, и оба имеют метод cost().Метод cost() внешнего класса вызывает метод cost() внутреннего класса.
код
interface Source{ void method();}
public class Decorator implements Source{
private Source source ;
public void decotate1(){
System.out.println("decorate");
}
@Override
public void method() {
decotate1();
source.method();
}
}
Разница между режимом украшения и режимом прокси
Паттерн Decorator фокусируется на динамическом добавлении методов к объекту, а паттерн Proxy фокусируется на управлении доступом к объекту.
-
Используя шаблон прокси, прокси-класс может скрывать определенную информацию об объекте от своих клиентов. Поэтому при использовании шаблона прокси мы часто создаем экземпляр объекта в классе прокси.
-
Когда мы используем шаблон декоратора, мы обычно делаем это, передавая исходный объект в качестве параметра конструктору декоратора.
Прокси-режим (Прокси)
Подробный пример кода:Блог woohoo.cn на.com/Daniels/afraid/8…
Введение
Определение режима прокси: режим проксиПредоставление прокси-объекта объекту,А прокси-объект управляет ссылкой на исходный объект.
С точки зрения непрофессионала, агентская модель распространена в нашей жизни.посредник.
Зачем использовать прокси-режим
-
изоляция посредничества
В некоторых случаях клиентский классне хочет или не может напрямую ссылаться на объект делегата, а объект прокси-класса может играть роль посредника между клиентским классом и объектом делегата,Его особенностью является то, что прокси-класс и класс делегата реализуют один и тот же интерфейс.
-
Открытый и закрытый принцип, функция увеличения
Настоящая бизнес-функция по-прежнему реализуется классом делегата., но некоторые госуслуги могут быть добавлены до и после выполнения бизнес-функций. Например, мы хотимДобавьте кеш и лог в проектЭти функции мы можем использовать для выполнения прокси-класса без необходимости открывать инкапсулированный класс делегата.
Какие существуют режимы прокси
статический прокси
даИсходный код, созданный программистами или автоматически сгенерированный специальными инструментами, при его компиляции. Файл прокси-класса .class создается до того, как программист запустит его.
Код: статический прокси для создания класса прокси:
package main.java.proxy.impl;
import main.java.proxy.BuyHouse;
public class BuyHouseProxy implements BuyHouse {
private BuyHouse buyHouse;
public BuyHouseProxy(final BuyHouse buyHouse) {
this.buyHouse = buyHouse;
}
@Override
public void buyHosue() {
System.out.println("买房前准备");
buyHouse.buyHosue();
System.out.println("买房后装修");
}
}
Сводка по статическим прокси
-
Преимущества: Возможно расширение функции целевого объекта при условии соблюдения принципа открытия и закрытия.
-
Минусы: мыНеобходимость создания прокси-класса для каждой службы требует слишком много работы. В то же время, как только интерфейс изменится, прокси-класс также должен быть изменен соответствующим образом.
Динамический прокси: механизм отражения JDK (интерфейсный прокси)
-
передается при запуске программыМеханизм отражения создается динамическииз.
-
Создайте прокси-объект для интерфейса, который необходимо перехватить, чтобы реализовать функцию перехвата метода интерфейса.
Код: написание динамического обработчика
package main.java.proxy.impl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxyHandler implements InvocationHandler {
private Object object;
public DynamicProxyHandler(final Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("买房前准备");
Object result = method.invoke(object, args);
System.out.println("买房后装修");
return result;
}
}
Код: написание тестовых классов
package main.java.proxy.test;
import main.java.proxy.BuyHouse;
import main.java.proxy.impl.BuyHouseImpl;
import main.java.proxy.impl.DynamicProxyHandler;
import java.lang.reflect.Proxy;
public class DynamicProxyTest {
public static void main(String[] args) {
BuyHouse buyHouse = new BuyHouseImpl();
BuyHouse proxyBuyHouse = (BuyHouse) Proxy.newProxyInstance(BuyHouse.class.getClassLoader(), new
Class[]{BuyHouse.class}, new DynamicProxyHandler(buyHouse));
proxyBuyHouse.buyHosue();
}
}
Резюме динамического агента
-
Преимущества: хотя по сравнению со статическими прокси, динамические прокси значительно сокращают наши задачи разработки, уменьшая при этом зависимость от бизнес-интерфейсов и уменьшая связанность.
-
Недостаток: проксировать можно только интерфейсы
Динамический прокси: прокси CGLIB
-
Принцип состоит в том, чтобы создать подкласс для класса с помощью технологии байт-кода и использовать технологию перехвата методов в подклассе для перехвата всех вызовов методов родительского класса и сплести сквозную логику в соответствии с тенденцией..
-
Но из-за наследстваТаким образом, вы не можете проксировать окончательные модифицированные классы.
-
И динамический прокси JDK, и динамический прокси CGLib являются основой для реализации Spring AOP.
Смотрите код на странице
Сводка прокси-сервера CGLIB: (отличие от прокси-сервера JDK:)
Динамические прокси-объекты, созданные CGLIB, более эффективны, чем динамические прокси-объекты, созданные JDK.,ноCGLIB требует гораздо больше времени для создания прокси-объектов, чем JDK..
- такДля одноэлементных объектов, поскольку нет необходимости часто создавать объекты, подходит CGLIB.Наоборот, целесообразнее использовать метод JDK.
- В то же время, поскольку CGLib принимает метод динамического создания подклассов, он не может проксировать окончательные модифицированные методы.
Внешний вид/Фасадный режим (Фасад)
блог woo woo woo.cn на.com/forum и IU/afraid/586…
Проще говоря, этот режим предназначен для инкапсуляции некоторых сложных процессов в интерфейс для облегчения их использования внешними пользователями. В этом режиме участвуют 3 персонажа.
Роль
1) Фасадная роль: ядро фасадного режима. Вызывается ролью клиента, которая знакома с функциональностью подсистемы. Комбинации нескольких функций предопределены внутренне на основе потребностей роли клиента.
2) Роль подсистемы: реализует функцию подсистемы. Клиенту неизвестна роль и фасад. Он может иметь взаимодействие внутри системы, а также может вызываться интерфейсом для внешнего мира.
3) Роль клиента: завершите функцию, которую необходимо реализовать, позвонив в Facede.
код
package com.huawei.facadeDesign.facade;
import org.apache.log4j.Logger;
import com.huawei.facadeDesign.children.CPU;
import com.huawei.facadeDesign.children.Disk;
import com.huawei.facadeDesign.children.Memory;
/**
* 门面类(核心)
* @author Administrator
*
*/
public class Computer
{
public static final Logger LOGGER = Logger.getLogger(Computer.class);
private CPU cpu;
private Memory memory;
private Disk disk;
public Computer()
{
cpu = new CPU();
memory = new Memory();
disk = new Disk();
}
public void start()
{
LOGGER.info("Computer start begin");
cpu.start();
disk.start();
memory.start();
LOGGER.info("Computer start end");
}
public void shutDown()
{
LOGGER.info("Computer shutDown begin");
cpu.shutDown();
disk.shutDown();
memory.shutDown();
LOGGER.info("Computer shutDown end...");
}
}
преимущество
-
Слабая связь: отделите клиент от подсистемы, упростив расширение и поддержку функций модуля внутри подсистемы;
-
Простота и удобство использования: Клиенту вообще не нужно знать внутреннюю реализацию подсистемы, или вообще не нужно знать внутренний состав подсистемы, ему нужно только взаимодействовать с классом Facade.
-
Лучшее разделение уровней доступа: некоторые методы являются внешними по отношению к системе, а некоторые используются для взаимодействия внутри системы. Подсистема концентрирует функции, выставленные наружу, на фасад, так что использование клиента может быть реализовано, а внутренние детали подсистемы хорошо скрыты.
Шаблон моста
Блог Woo Woo.cn на.com/monkey information/AR…
имея в виду
В программной системе некоторые типы имеют изменения в двух или более измерениях из-за своей собственной логики, так как же быть с этим «многомерным изменением»?
Как можно использовать объектно-ориентированные методы, чтобы сделать тип легко изменяемым в нескольких направлениях без дополнительной сложности? Это для использования режима моста.
Изменение сверху вниз
код
Подробный код см. на справочной странице.
static void Main(string[] args){
//男人开着公共汽车在高速公路上行驶;
Console.WriteLine("=========================");
AbstractRoad Road3 = new SpeedWay();
Road3.Car = new Bus();
people p = new Man();
p.Road = Road3;
p.Run();
Console.Read();
}
Композитный режим
блог woo woo woo.cn на.com/laifuxiao/afraid/68…
Шаблоны композиции предназначены для представления этих иерархий, в то время как части и целые также могут иметь одну и ту же структуру, общую для папок или деревьев.
определение
Режим комбинирования определяет, как рекурсивно комбинировать объекты-контейнеры и конечные объекты, чтобы клиенты могли обрабатывать их согласованно, не различая их во время использования.
Одна вещь, на которую следует обратить внимание при использовании комбинированного режима, также является наиболее важной частью комбинированного режима:Конечные объекты и составные объекты реализуют один и тот же интерфейс. Вот почему режим композиции может последовательно обрабатывать конечные узлы и узлы объектов.
Роль
1. Компонент: объекты в композиции объявляют интерфейс и, при необходимости, реализуют поведение интерфейса по умолчанию, общее для всех классов. Объявите интерфейс для доступа и управления подкомпонентами компонента.
2.Leaf: Листовой объект. Листовые узлы не имеют дочерних узлов.
3.Composite: объект-контейнер, который определяет поведение узла ветвления для хранения подкомпонентов и реализации операций, связанных с подкомпонентами в интерфейсе компонента, таких как добавление (добавить) и удаление (удаление) и т. д.
Применимая сцена
1. Необходимо представить иерархию целого или части объекта.В иерархии с целым и частью можно надеяться, что различие между целым и частью можно игнорировать, чтобы с ними можно было обращаться последовательно.
2. Разрешить клиентам игнорировать изменения на разных уровнях объектов, и клиенты могут программировать абстрактные компоненты, не заботясь о деталях иерархии объектов.
Наилегчайший вес
Блог Woohoo.cn on.com/Chen's College/Afraid/3…
определение
Так называемый режим Flyweight заключается в том, что работающая технология совместного использования эффективно поддерживает повторное использование большого количества мелкозернистых объектов, поэтому режим Flyweight требует объектов, которыми можно делиться.Должен быть мелкозернистый объект.
-
Внутреннее состояние: общая часть внутри легковесного объекта, которая не меняется при изменении внешней среды.
-
Внешнее состояние: состояние, которое изменяется по мере изменения среды, и состояние, которым нельзя поделиться, является внешним состоянием.
код
Класс FlyweightFactory
Используйте HashMap, чтобы сохранить созданный цвет.
public class FlyweightFactory{
static Map<String, Shape> shapes = new HashMap<String, Shape>();
public static Shape getShape(String key){
Shape shape = shapes.get(key);
//如果shape==null,表示不存在,则新建,并且保持到共享池中
if(shape == null){
shape = new Circle(key);
shapes.put(key, shape);
}
return shape;
}
public static int getSum(){
return shapes.size();
}
}
Клиентская программа: Client.java
public class Client {
public static void main(String[] args) {
Shape shape1 = FlyweightFactory.getShape("红色");
shape1.draw();
Shape shape2 = FlyweightFactory.getShape("灰色");
shape2.draw();
Shape shape3 = FlyweightFactory.getShape("绿色");
shape3.draw();
Shape shape4 = FlyweightFactory.getShape("红色");
shape4.draw();
Shape shape5 = FlyweightFactory.getShape("灰色");
shape5.draw();
Shape shape6 = FlyweightFactory.getShape("灰色");
shape6.draw();
System.out.println("一共绘制了"+FlyweightFactory.getSum()+"中颜色的圆形");
}
}
Ссылаться на
Цзяньшу Даниэль:www.jianshu.com/nb/10186551
Github:GitHub.com/CY C2018/int…
Cainiao.com:ууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууу
Пополнить:
Резюме 23 шаблонов проектирования: