мост
Введение
Шаблон моста представляет собой шаблон создания, используемый для отрыва абстракции от его реализации.Мост использует инкапсуляцию, агрегацию и может использовать наследование для разделения обязанностей на разные классы.
Цель
- Отделите абстракцию от ее реализации, которая позволяет независимо варьироваться.
- Публиковать интерфейс в иерархии наследования и сверять реализацию в своей собственной иерархии наследования.
Схема проектирования
Объекты, участвующие в этом шаблоне, представлены на следующей диаграмме:
Abstraction
определяет интерфейс абстракции и поддерживает ссылку на объект типаImplementor
RefinedAbstraction
расширяет интерфейс, определяемыйAbstraction Implementor
определяет интерфейс для объектов реализацииConcreteImplementor
реализуетImplementor
интерфейс и определяет его конкретную реализацию
Реализация
Подумайте о создании пакета пользовательского интерфейса, который поддерживает рисование различных форм на экране с помощью технологий поддержкиOpenGL
иDirect2D
рендеринга.В нашем конкретном примере мы должны иметь возможность рисовать круг, поддерживая обе системы рендеринга.
Для этого мы должны отделитьCircle
структуру от ее реализации:
// Circle represents a circle shape
type Circle struct {
// DrawingContext for this circle
DrawingContext Drawer
// Center of the circle
Center Point
// Radius of the circle
Radius float64
}
// Draw draws a circle
func (circle *Circle) Draw() error {
rect := Rect{
Location: Point{
X: circle.Center.X - circle.Radius,
Y: circle.Center.Y - circle.Radius,
},
Size: Size{
Width: 2 * circle.Radius,
Height: 2 * circle.Radius,
},
}
return circle.DrawingContext.DrawEllipseInRect(rect)
}
Drawer
Определяет контракт междуCircle
абстракцией и ее реализацией:
// Drawer draws on the underlying graphics device
type Drawer interface {
// DrawEllipseInRect draws an ellipse in rectanlge
DrawEllipseInRect(Rect) error
}
Для каждой поддерживаемой технологии рендеринга мы должны реализовать структуру, которая подчиняетсяDrawer
интерфейсу:
Это пример реализацииOpenGL
ящика:
// OpenGL drawer
type OpenGL struct{}
// DrawEllipseInRect draws an ellipse in rectangle
func (gl *OpenGL) DrawEllipseInRect(r Rect) error {
fmt.Printf("OpenGL is drawing ellipse in rect %v", r)
return nil
}
Это пример реализацииDirect2D
ящика:
// Direct2D drawer
type Direct2D struct{}
// DrawEllipseInRect draws an ellipse in rectangle
func (d2d *Direct2D) DrawEllipseInRect(r Rect) error {
fmt.Printf("Direct2D is drawing ellipse in rect %v", r)
return nil
}
Затем мы можем легко отобразить круг, используя желаемую систему рисования.Мы должны просто изменить реализацию, установивDrawingContext
поле:
openGL := &uikit.OpenGL{}
direct2D := &uikit.Direct2D{}
circle := &uikit.Circle{
Center: uikit.Point{X: 100, Y: 100},
Radius: 50,
}
circle.DrawingContext = openGL
circle.Draw()
circle.DrawingContext = direct2D
circle.Draw()
Выводы
Шаблон моста разработан заранее, чтобы абстракция и реализация менялись независимо.Это позволяет нам самостоятельно изменять реализацию из ее абстракции.