이 글은 Java의 전략 패턴과 템플릿 메소드 패턴(코드 포함)을 소개합니다. 필요한 친구들이 참고할 수 있기를 바랍니다.
전략 패턴
소개
전략 패턴은 객체의 행동 패턴에 속합니다. 그 목적은 알고리즘 세트에 대한 공통 인터페이스를 사용하여 각 알고리즘을 독립적인 클래스로 캡슐화하여 서로 교체할 수 있도록 하는 것입니다. 전략 패턴을 사용하면 클라이언트에 영향을 주지 않고 알고리즘을 변경할 수 있습니다.
주된 목적은 유사한 알고리즘을 정의하여 if else 문의 작성을 대체하는 것이며 언제든지 서로 대체될 수 있습니다.
전략 모드는 크게 환경적 역할(Context), 추상적인 전략 역할(Strategy), 구체적인 전략 역할(ConcreteStrategy)의 세 가지 역할로 구성됩니다.
환경 역할(컨텍스트): 전략 클래스에 대한 참조를 보유하고 이를 클라이언트에 제공합니다.
추상 전략 역할(Strategy): 이는 일반적으로 인터페이스나 추상 클래스에 의해 구현되는 추상 역할입니다. 이 역할은 특정 정책 클래스에 필요한 모든 인터페이스를 제공합니다.
Concrete Strategy Role(ConcreteStrategy): 관련 알고리즘 또는 동작을 패키지합니다.
예제 그림은 다음과 같습니다.
이해를 돕기 위해 Java를 처음 배울 때 사용했던 계산 방법을 살펴보겠습니다.
계산을 위해 계산기를 사용할 때는 덧셈, 뺄셈, 곱셈, 나눗셈 방식을 자주 사용합니다. 두 숫자를 더한 합을 구하려면 "+" 기호를 사용해야 하고, 뺄셈의 차이를 구하려면 "-" 기호를 사용해야 하는 식입니다. 문자열 비교를 통해 if/else를 사용하는 일반적인 메소드를 작성할 수 있지만, 계산된 기호가 추가될 때마다 후속 계산 메소드가 추가, 수정 또는 삭제되면 해당 코드를 원래 메소드에 추가해야 합니다. 후속 유지 관리를 어렵게 만듭니다.
그러나 이 방법들 중에서는 기본 방법이 정해져 있는 것을 발견했는데, 이는 나중에 다른 계산 규칙이 추가되더라도 효과적으로 판단을 피할 수 있는 전략 패턴을 통해 개발할 수 있다는 것입니다. 유연하게 조정.
먼저 추상적인 전략 역할을 정의하고 계산 방법을 갖습니다.
interface CalculateStrategy { int doOperation(int num1, int num2); }
그런 다음 덧셈, 뺄셈, 곱셈, 나눗셈의 구체적인 전략적 역할을 정의하고 구현하세요.
그러면 코드는 다음과 같습니다.
class OperationAdd implements CalculateStrategy { @Override public int doOperation(int num1, int num2) { return num1 + num2; } } class OperationSub implements CalculateStrategy { @Override public int doOperation(int num1, int num2) { return num1 - num2; } } class OperationMul implements CalculateStrategy { @Override public int doOperation(int num1, int num2) { return num1 * num2; } } class Operationp implements CalculateStrategy { @Override public int doOperation(int num1, int num2) { return num1 / num2; } }
마지막으로 환경 역할을 정의하고 클라이언트가 사용할 컴퓨팅 인터페이스를 제공합니다.
코드는 다음과 같습니다.
class CalculatorContext { private CalculateStrategy strategy; public CalculatorContext(CalculateStrategy strategy) { this.strategy = strategy; } public int executeStrategy(int num1, int num2) { return strategy.doOperation(num1, num2); } }
작성 후 테스트해보겠습니다.
테스트 코드는 다음과 같습니다.
public static void main(String[] args) { int a=4,b=2; CalculatorContext context = new CalculatorContext(new OperationAdd()); System.out.println("a + b = "+context.executeStrategy(a, b)); CalculatorContext context2 = new CalculatorContext(new OperationSub()); System.out.println("a - b = "+context2.executeStrategy(a, b)); CalculatorContext context3 = new CalculatorContext(new OperationMul()); System.out.println("a * b = "+context3.executeStrategy(a, b)); CalculatorContext context4 = new CalculatorContext(new Operationp()); System.out.println("a / b = "+context4.executeStrategy(a, b)); }
출력 결과:
a + b = 6 a - b = 2 a * b = 8 a / b = 2
전략 패턴 장점:
좋은 확장성, 객체 구조를 수정하지 않고도 새 알고리즘에 대한 새 클래스를 추가할 수 있습니다.
유연성이 뛰어나 알고리즘을 자유롭게 전환할 수 있습니다.
전략 모드 단점:
더 많은 전략 클래스를 사용하면 시스템이 더 복잡해집니다. ;
클라이언트는 호출하기 전에 모든 전략 클래스를 알아야 합니다.
사용 시나리오:
시스템에 많은 클래스가 있고 클래스 간의 차이점은 동작뿐인 경우 다음을 사용합니다. 전략 패턴은 객체가 여러 동작 중에서 하나의 동작을 동적으로 선택하도록 허용할 수 있습니다.
시스템은 여러 알고리즘 중 하나를 동적으로 선택해야 합니다.
객체에 동작이 많으면 패턴이 적절하게 사용되지 않습니다.
Introduction
템플릿 패턴(Template Pattern)에서 추상 클래스는 메소드/템플릿을 실행하는 방법을 공개적으로 정의합니다. 해당 하위 클래스는 필요에 따라 메서드 구현을 재정의할 수 있지만 호출은 추상 클래스에 정의된 방식으로 이루어집니다. 이러한 유형의 디자인 패턴은 행동 패턴입니다. 한 번의 작업으로 알고리즘의 골격을 정의하고 일부 단계를 하위 클래스로 연기합니다.
템플릿 모드의 주요 아이디어는 템플릿을 만들어 고객에게 제공하여 호출하는 것입니다. 우리가 생활에서 자주 사용하는 이력서 템플릿, 계약 템플릿 등 외에도 Java에서 사용되는 매우 고전적인 템플릿, 즉 Servlet도 있습니다. HttpService 클래스는 7개의 do 중 하나를 호출하는 service() 메서드를 제공합니다. 방법 또는 클라이언트 호출에 대한 여러 가지 완전한 응답. 이러한 do 메소드는 HttpServlet의 특정 하위 클래스에서 제공되어야 합니다.
템플릿 모드는 크게 추상 템플릿 역할과 콘크리트 템플릿 역할로 구성됩니다.
抽象模板(Abstract Template): 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤;定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
具体模板(Concrete Template): 实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤;每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
示例图如下:
这里为了方便理解,我们依旧使用一个简单的示例来加以说明。
我们以前在玩魂斗罗、双截龙、热血物语、忍者神龟等等游戏的时候,都需要在小霸王游戏机上插卡,然后启动游戏才能玩,其中魂斗罗这种游戏,启动游戏之后就可以直接玩了,但是忍者神龟这种游戏则在启动游戏之后,需要选择其中一个角色才能开始玩。那么我们可以根据这个场景写出一个通用的模板,主要包含启动游戏,玩游戏,结束游戏这几个必须实现的方法,选择人物这个方法改成可选。
那么这个抽象类的代码如下:
abstract class Game{ //启动游戏 protected abstract void runGame(); //选择人物 protected void choosePerson() {}; //开始玩游戏 protected abstract void startPlayGame(); //结束游戏 protected abstract void endPlayGame(); //模板方法 public final void play() { runGame(); choosePerson(); startPlayGame(); endPlayGame(); } }
定义好该抽象类之后,我们再来定义具体模板实现类。这里定义两个游戏类,一个是魂斗罗,一个忍者神龟。
那么代码如下:
class ContraGame extends Game{ @Override protected void runGame() { System.out.println("启动魂斗罗II..."); } @Override protected void startPlayGame() { System.out.println("1P正在使用S弹打aircraft..."); } @Override protected void endPlayGame() { System.out.println("1P被流弹打死了,游戏结束!"); } } class TMNTGame extends Game{ @Override protected void runGame() { System.out.println("启动忍者神龟III..."); } @Override protected void choosePerson() { System.out.println("1P选择了Raph !"); } @Override protected void startPlayGame() { System.out.println("Raph正在使用绝技 “火箭头槌” "); } @Override protected void endPlayGame() { System.out.println("Raph 掉进井盖里死了,游戏结束了! "); } }
最后再来进行测试,测试代码如下:
public static void main(String[] args) { Game game = new ContraGame(); game.play(); System.out.println(); game = new TMNTGame(); game.play(); }
输出结果:
启动魂斗罗II...1P正在使用S弹打aircraft...1P被流弹打死了,游戏结束! 启动忍者神龟III...1P选择了Raph ! Raph正在使用绝技 “火箭头槌” Raph 掉进井盖里死了,游戏结束了!
模板模式优点:
扩展性好,对不变的代码进行封装,对可变的进行扩展;
可维护性好,因为将公共代码进行了提取,使用的时候直接调用即可;
模板模式缺点:
因为每一个不同的实现都需要一个子类来实现,导致类的个数增加,会使系统变得复杂;
使用场景:
有多个子类共有逻辑相同的方法;
重要的、复杂的方法,可以考虑作为模板方法。
注意事项:
为防止恶意操作,一般模板方法都加上 final 关键词!
위 내용은 Java의 전략 패턴 및 템플릿 메소드 패턴 소개(코드 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!