-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
214 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
## 策略模式(StrategyPattern) | ||
### 概述 | ||
> 策略模式(Strategy Pattern),将各种算法封装到具体的类中,作为一个抽象策略类的子类,使得它们可以互换。客户端可以自行决定使用哪种算法。 | ||
### 结构图和说明 | ||
结构图如下图所示 | ||
![image]( ) | ||
1. Strategy 策略接口或者(抽象策略类),定义策略执行接口 | ||
2. ConcreteStrategy 具体策略类 | ||
3. Context 上下文类,持有具体策略类的实例,并负责调用相关的算法 | ||
### 代码实现 | ||
(1)抽象策略类 | ||
|
||
public interface Strategy { | ||
public void operation(String input); | ||
} | ||
|
||
(2)具体策略类 | ||
|
||
public class ConcreteStrategyA implements Strategy { | ||
@Override | ||
public void operation(String input) { | ||
//do something | ||
System.out.println("ConcreteStrategyA do something : " + input); | ||
} | ||
} | ||
|
||
(3)策略上下文,负责调用具体的策略 | ||
|
||
public class SimpleContext { | ||
private Strategy strategy; | ||
|
||
public SimpleContext(Strategy strategy) { | ||
this.strategy = strategy; | ||
} | ||
|
||
public void action(String input) { | ||
strategy.operation(input); | ||
} | ||
} | ||
|
||
(4)客户端,调用策略模式 | ||
|
||
public class Client { | ||
public static void main(String[] args) { | ||
Strategy strategy = new ConcreteStrategyA(); | ||
SimpleContext context = new SimpleContext(strategy); | ||
context.action("hello world"); | ||
} | ||
} | ||
|
||
|
||
从上面的示例可以看出,策略模式仅仅封装算法,提供新的算法插入到已有系统中,以及老算法从系统中“退休”的方法,策略模式并不决定在何时使用何种算法。在什么情况下使用什么算法是由客户端决定的。 | ||
|
||
|
||
### 小结 | ||
**策略模式的重心** | ||
|
||
策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。 | ||
|
||
**算法的平等性** | ||
|
||
策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法,大家的地位是完全一样的,正因为这个平等性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。 | ||
|
||
所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。 | ||
|
||
**运行时策略的唯一性** | ||
|
||
运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。 | ||
|
||
**公有的行为** | ||
|
||
经常见到的是,所有的具体策略类都有一些公有的行为。这时候,就应当把这些公有的行为放到共同的抽象策略角色Strategy类里面。当然这时候抽象策略角色必须要用Java抽象类实现,而不能使用接口。 | ||
#### 优点 | ||
1. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。 | ||
|
||
2. 使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。 | ||
|
||
#### 缺点 | ||
1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。 | ||
|
||
2. 由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
## 装饰器模式(DecoratorPattern) | ||
### 概念 | ||
> 装饰模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。通常给对象添加功能,要么直接修改对象添加相应的功能,要么派生对应的子类来扩展,抑或是使用对象组合的方式。显然,直接修改对应的类这种方式并不可取。在面向对象的设计中,而我们也应该尽量使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式,可以很灵活的给对象添加所需要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。总之,装饰模式是通过把复杂的功能简单化,分散化,然后再运行期间,根据需要来动态组合的这样一个模式 | ||
### 模式结构说明 | ||
|
||
装饰模式的结构如下图所示 | ||
|
||
![image](./2011110423171991.jpg) | ||
Component(原始类):组件对象的接口,可以给这些对象动态的添加职责; | ||
|
||
ConcreteComponent(继承类):具体的组件对象,实现了组件接口。该对象通常就是被装饰器装饰的原始对象,可以给这个对象添加职责; | ||
|
||
Decorator(装饰器基类):所有装饰器的父类,需要定义一个与组件接口一致的接口(主要是为了实现装饰器功能的复用,即具体的装饰器A可以装饰另外一个具体的装饰器B,因为装饰器类也是一个Component),并持有一个Component对象,该对象其实就是被装饰的对象。如果不继承组件接口类,则只能为某个组件添加单一的功能,即装饰器对象不能在装饰其他的装饰器对象。 | ||
|
||
ConcreteDecorator(装饰器实现类):具体的装饰器类,实现具体要向被装饰对象添加的功能。用来装饰具体的组件对象或者另外一个具体的装饰器对象。 | ||
|
||
### 代码实现(in java) | ||
(1)组件对象的接口,可以给这些对象动态添加职责 | ||
``` | ||
public interface Component { | ||
public void operation(); | ||
} | ||
``` | ||
(2)具体实现组件对象接口的对象 | ||
``` | ||
public class ConcreateComponent implements Component { | ||
@Override | ||
public void operation() { | ||
//do something | ||
} | ||
} | ||
``` | ||
(3)装饰器接口,维持一个指向组件对象的接口对象, 并定义一个与组件接口一致的接口 | ||
``` | ||
public abstract class Decorator implements Component { | ||
private Component component; | ||
public Decorator(Component component) { | ||
this.component = component; | ||
} | ||
@Override | ||
public void operation() { | ||
//转发请求给组件对象,可以在转发之后执行一些附加动作 | ||
component.operation(); | ||
} | ||
} | ||
``` | ||
装饰器的具体实现对象,向组件对象添加职责,operationFirst(),operationLast()为前后需要添加的功能。具体的装饰器类ConcreteDecoratorB代码相似 | ||
``` | ||
public class ConcreteDecoratorA extends Decorator { | ||
public ConcreteDecoratorA(Component component) { | ||
super(component); | ||
} | ||
private void operationFirst() { | ||
//在调用父类的operation方法之前需要执行的操作 | ||
} | ||
private void operationLast() { | ||
//在调用父类的operation方法之后需要执行的操作 | ||
} | ||
public void operation() { | ||
//调用父类的方法,可以在调用前后执行一些附加动作 | ||
operationFirst(); //添加的功能 | ||
super.operation(); //这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能 | ||
operationLast(); //添加的功能 | ||
} | ||
} | ||
``` | ||
(5)客户端使用装饰器 | ||
``` | ||
public class Client { | ||
public static void main(String[] args) { | ||
Component component = new ConcreateComponent(); | ||
Decorator myDecorator = new ConcreteDecoratorA(new ConcreteDecoratorB(component)); | ||
myDecorator.operation(); | ||
} | ||
} | ||
``` | ||
### 总结 | ||
Java中的IO是明显的装饰器模式的运用。FilterInputStream,FilterOutputStream,FilterRead,FilterWriter分别为具体装饰器的父类,相当于Decorator类,它们分别实现了InputStream,OutputStream,Reader,Writer类(这些类相当于Component,是其他组件类的父类,也是Decorator类的父类)。继承自InputStream,OutputStream,Reader,Writer这四个类的其他类是具体的组件类,每个都有相应的功能,相当于ConcreteComponent类。而继承自FilterInputStream,FilterOutputStream,FilterRead,FilterWriter这四个类的其他类就是具体的装饰器对象类,即ConcreteDecorator类。通过这些装饰器类,可以给我们提供更加具体的有用的功能。如FileInputStream是InputStream的一个子类,从文件中读取数据流,BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区类保存输入流中的数据。我们使用如下的代码来使用BufferedInputStream装饰FileInputStream,就可以提供一个内存缓冲区来保存从文件中读取的输入流。 | ||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); //其中file为某个具体文件的File或者FileDescription对象 | ||
#### 在以下两种情况下可以考虑使用装饰器模式: | ||
(1)需要在不影响其他对象的情况下,以动态、透明的方式给对象添加职责。 | ||
|
||
(2)如果不适合使用子类来进行扩展的时候,可以考虑使用装饰器模式。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters