나는 dofactory , wikipedia 및 많은 사이트 에서 많은 기사를 읽으려고 노력했습니다 . 브리지 패턴과 전략 패턴의 차이점에 대해 전혀 모릅니다.
둘 다 구현에서 추상화를 분리하고 런타임에 구현을 변경할 수 있음을 알고 있습니다.
하지만 어떤 상황에서 전략을 사용해야하는지, 어떤 상황에서 브리지를 사용해야하는지 여전히 잘 모르겠습니다.
답변
의미론. 에서 위키 피 디아 :
전략 패턴의 UML 클래스 다이어그램은 Bridge 패턴의 다이어그램과 동일합니다. 그러나이 두 가지 디자인 패턴은 의도가 동일하지 않습니다. 전략 패턴은 행동을위한 것이지만 브리지 패턴은 구조를위한 것입니다.
컨텍스트와 전략 간의 결합은 추상화와 Bridge 패턴의 구현 간의 결합보다 더 엄격합니다.
내가 이해했듯이 외부 소스에서 제공 할 수있는 동작을 추상화 할 때 전략 패턴을 사용하고 (예 : config는 일부 플러그인 어셈블리를로드하도록 지정할 수 있음), 사용할 때 브리지 패턴을 사용하고 있습니다. 코드를 좀 더 깔끔하게 만들기 위해 동일한 구조를 사용합니다. 실제 코드는 매우 유사하게 보일 것입니다. 단지 약간 다른 이유로 패턴을 적용하는 것 입니다.
답변
브리지 패턴은 구조적 패턴입니다 (소프트웨어 구성 요소를 어떻게 구축합니까?). 전략 패턴은 동적 패턴입니다 (소프트웨어에서 동작을 어떻게 실행 하시겠습니까?).
구문은 비슷하지만 목표는 다릅니다.
- 전략 : 작업을 수행하는 더 많은 방법이 있습니다. 전략을 사용하면 런타임에 알고리즘을 선택할 수 있으며 컴파일 타임에 많은 부작용없이 단일 전략을 수정할 수 있습니다.
- Bridge : 인터페이스와 클래스의 계층을 분할하고 추상 참조와 결합 할 수 있습니다 ( 설명 참조 ).
답변
전략:
- 전략에 연결된 컨텍스트 : 컨텍스트 클래스 (추상적이지만 실제로는 인터페이스가 아닙니다! 전체 구현이 아닌 특정 동작을 캡슐화하려는 경우)는 전략 인터페이스 참조 및 전략 동작을 호출하는 구현 을 알고 / 포함합니다 . 그것.
-
의도는 런타임에 동작을 바꾸는 기능입니다.
class Context { IStrategy strategyReference; void strategicBehaviour() { strategyReference.behave(); } }
다리
- 구현에 연결되지 않은 추상화 : 추상화 인터페이스 (또는 대부분의 동작 추상이있는 추상 클래스)는 구현 인터페이스 참조를 알거나 포함하지 않습니다.
-
의도는 구현에서 추상화를 완전히 분리하는 것입니다.
interface IAbstraction { void behaviour1(); ..... } interface IImplementation { void behave1(); void behave2(); ..... } class ConcreteAbstraction1 implements IAbstraction { IImplementation implmentReference; ConcreteAbstraction1() { implmentReference = new ImplementationA() // Some implementation } void behaviour1() { implmentReference.behave1(); } ............. } class ConcreteAbstraction2 implements IAbstraction { IImplementation implmentReference; ConcreteAbstraction1() { implmentReference = new ImplementationB() // Some Other implementation } void behaviour1() { implmentReference.behave2(); } ............. }
답변
저도 같은 생각을하고 있었지만 최근에는 브리지를 사용해야했고 브리지가 전략을 사용하고 컨텍스트에 추상화를 추가하여 나중에 클라이언트를 변경하지 않고도 더 많은 변경을 수행 할 수 있다는 것을 깨달았습니다. 추상화없이 Strategy를 사용하면 디자인이 유연하지 않아 나중에 클라이언트를 변경해야 할 수 있습니다. 그러나 전체 교량을 사용하면 디자인이 훨씬 더 유연 해집니다. 여기에서 Strategy에서 Bridge 로의 전환이 어떻게 더 많은 유연성을 제공하는지 확인할 수 있습니다. 또한 이제 “비자”와 “마스터”는 카드뿐만 아니라 휴대폰과 칩에서도 사용할 수 있다고 가정합니다. 브리지를 사용하면 해당 지원을 추가하는 것이 훨씬 쉽습니다.
답변
교량 : (구조적 패턴)
브리지 패턴은 추상화와 구현을 분리하고 둘 다 독립적으로 변할 수 있습니다.
다음과 같은 경우이 패턴을 사용합니다.
- 추상화와 구현은 컴파일 타임에 결정되지 않았습니다.
- 추상화 및 구현은 독립적으로 변경되어야합니다.
- 추상화 구현의 변경 사항은 호출자 응용 프로그램에 영향을주지 않아야합니다.
- 고객은 구현 세부 사항으로부터 격리되어야합니다.
전략 : (행동 패턴)
전략 패턴을 사용하면 런타임에 알고리즘 제품군의 여러 알고리즘간에 전환 할 수 있습니다.
다음과 같은 경우 전략 패턴을 사용합니다.
- 여러 버전의 알고리즘이 필요합니다.
- 클래스의 동작은 런타임에 동적으로 변경되어야합니다.
- 조건문 피하기
관련 게시물:
답변
디자인 패턴 유형
- 행동 : 패턴은 클래스 또는 객체가 상호 작용하고 책임을 분배하는 방식을 특성화합니다.
- 구조적 : 패턴은 클래스 또는 객체의 구성을 처리합니다.
- Creational : 패턴은 객체 생성 과정에 관심이 있습니다.
교량 (구조)
리모컨을 가져 가세요. 리모컨에는 1-6 버튼이 있습니다. 이것은 위 다이어그램의 구체적인 클래스입니다. 리모컨이 TV 또는 DVD에 사용되는지 여부에 따라 각 버튼이 다르게 작동합니다. 각 버튼의 기능은 구현 자 인터페이스의 구현에서 추상화됩니다.
이를 통해 각 장치에서 리모컨이 작동하는 방식을 변경할 수 있습니다.
전략 (행동)
전략에서 우리가 원격 시나리오를보고 있다면. “상태”는 컨텍스트의 상태 참조를 변경하여 교체하는 전체 원격입니다. “concreteStateA”(TV 원격) “concreteStateB”(DVD 원격)입니다.
추가 자료 :
답변
-
Strategy Pattern은 행동 결정에 사용되며 Bridge Pattern은 구조 결정에 사용됩니다.
-
Brigde Pattern은 구현 세부 사항에서 추상 요소를 분리하는 반면, 전략 패턴은 알고리즘을보다 상호 교환 가능하게 만드는 데 관심이 있습니다.
Swift의 전략 패턴 :
protocol PrintStrategy {
func print(_ string: String) -> String
}
class Printer {
let strategy: PrintStrategy
init(strategy: PrintStrategy) {
self.strategy = strategy
}
func print(_ string: String) -> String {
return self.strategy.print(string)
}
}
class UpperCaseStrategy: PrintStrategy {
internal func print(_ string: String) -> String {
return string.uppercased()
}
}
class LowerCaseStrategy: PrintStrategy {
internal func print(_ string: String) -> String {
return string.lowercased()
}
}
var lower = Printer(strategy: LowerCaseStrategy())
lower.print("I love Software Patterns")
var upper = Printer(strategy: UpperCaseStrategy())
upper.print("I love Software Patterns")
Swift의 Brigde 패턴 :
protocol Appliance {
func run()
}
protocol Switch {
let appliance: Appliance {get set}
func turnOn()
}
class RemoteControl: Switch {
var appliance: Appliance
init(appliance: Appliance) {
self.appliance = appliance
}
internal func turnOn() {
appliance.run()
}
}
class TV: Appliance {
internal func run() {
print("TV is ON")
}
}
class Stereo: Appliance {
internal func run() {
print("Stereo is ON")
}
}
var tvRemote = RemoteControl.init(appliance: TV())
tvRemote.turnOn()
var stereoRemote = RemoteControl.init(appliance: Stereo())
stereoRemote.turnOn()