forked from yoyiyi/SoleilNotes
-
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
13 changed files
with
1,305 additions
and
2 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
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,92 @@ | ||
## 1 概述 | ||
|
||
运用**共享技术(共享对象)**来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销,从而提高系统资源的利用率。 | ||
|
||
享元(Flyweight )模式中存在以下两种状态: | ||
|
||
1. 内部状态,即不会随着环境的改变而改变的可共享部分。 | ||
2. 外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。 | ||
|
||
享元模式的主要有以下角色: | ||
|
||
- 抽象享元角色(Flyweight):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)。 | ||
- 具体享元(Concrete Flyweight)角色 :它实现了抽象享元类,称为享元对象;在具体享元类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。 | ||
- 非享元(Unsharable Flyweight)角色 :并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。 | ||
- 享元工厂(Flyweight Factory)角色 :负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。 | ||
|
||
## 2 例子 | ||
|
||
俄罗斯方块有不同的形状,每个不同的方块都是一个实例对象。 | ||
|
||
```java | ||
public abstract class AbstractBox { | ||
public abstract String getShape(); | ||
|
||
public void display(String color) { | ||
System.out.println("方块形状:" + this.getShape() + " 颜色:" + color); | ||
} | ||
} | ||
|
||
|
||
public class IBox extends AbstractBox { | ||
|
||
@Override | ||
public String getShape() { | ||
return "I"; | ||
} | ||
} | ||
|
||
public class LBox extends AbstractBox { | ||
|
||
@Override | ||
public String getShape() { | ||
return "L"; | ||
} | ||
} | ||
|
||
public class OBox extends AbstractBox { | ||
|
||
@Override | ||
public String getShape() { | ||
return "O"; | ||
} | ||
} | ||
|
||
//创建一个工厂类 | ||
public class BoxFactory { | ||
private static HashMap<> map; | ||
|
||
private BoxFactory() { | ||
map = new HashMap<String, AbstractBox>(); | ||
AbstractBox iBox = new IBox(); | ||
AbstractBox lBox = new LBox(); | ||
AbstractBox oBox = new OBox(); | ||
map.put("I", iBox); | ||
map.put("L", lBox); | ||
map.put("O", oBox); | ||
} | ||
|
||
public static final BoxFactory getInstance() { | ||
return SingletonHolder.INSTANCE; | ||
} | ||
|
||
private static class SingletonHolder { | ||
private static final BoxFactory INSTANCE = new BoxFactory(); | ||
} | ||
|
||
public AbstractBox getBox(String key) { | ||
return map.get(key); | ||
} | ||
} | ||
``` | ||
|
||
## 3 优缺点 | ||
|
||
优点: | ||
|
||
- 极大减少内存中相似或相同对象数量,节约系统资源,提供系统性能 | ||
- 享元模式中的外部状态相对独立,且不影响内部状态 | ||
|
||
缺点: | ||
|
||
* 为了使对象可以共享,需要将享元对象的部分状态外部化,分离内部状态和外部状态,使程序逻辑复杂 |
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,95 @@ | ||
## 1 概述 | ||
|
||
又称为**部分整体模式**,是用于把一组**相似**的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。属于结构型模式,它创建了对象组的**树形结构**。 | ||
|
||
组合模式主要包含三种角色: | ||
|
||
- 抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。 | ||
- 树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构。 | ||
- 叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位。 | ||
|
||
分类: | ||
|
||
* 透明组合模式:抽象根节点角色中声明了所有用于管理成员对象的方法,add,remove 等。 | ||
* 安全组合模式:抽象构件角色中没有声明任何用于管理成员对象的方法。 | ||
|
||
## 2 例子 | ||
|
||
一个公司组织架构,有许多员工,员工有上下级关系。 | ||
|
||
```java | ||
public class Employee { | ||
private String name; | ||
private List<Employee> employees; | ||
|
||
public Employee(String name) { | ||
this.name = name; | ||
employees = new ArrayList<>(); | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void add(Employee employee) { | ||
employees.add(employee); | ||
} | ||
|
||
public void remove(Employee employee) { | ||
employees.remove(employee); | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
public List<Employee> getEmployees() { | ||
return employees; | ||
} | ||
|
||
public void setEmployees(List<Employee> employees) { | ||
this.employees = employees; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Employee{" + | ||
"name='" + name + '\'' + | ||
", employees=" + employees + | ||
'}'; | ||
} | ||
} | ||
|
||
public class TestClient { | ||
public static void main(String[] args) { | ||
final Employee a = new Employee("总裁"); | ||
final Employee b1 = new Employee("人事经理"); | ||
final Employee b2 = new Employee("财务经理"); | ||
|
||
final Employee c1 = new Employee("人事专员1"); | ||
final Employee c2 = new Employee("人事专员2"); | ||
|
||
|
||
a.add(b1); | ||
a.add(b2); | ||
|
||
b1.add(c1); | ||
b1.add(c2); | ||
|
||
System.out.println(a); | ||
for (Employee employee : a.getEmployees()) { | ||
System.out.println(employee); | ||
for (Employee sub : employee.getEmployees()) { | ||
System.out.println(sub); | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## 3 优缺点 | ||
|
||
- 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。 | ||
- 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。 | ||
- 在组合模式中增加新的树枝节点和叶子节点都很方便,无须对现有类库进行任何修改,符合“开闭原则”。 | ||
- 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。 |
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,87 @@ | ||
## 1 概述 | ||
|
||
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。 | ||
|
||
模板方法(Template Method)模式包含以下主要角色: | ||
|
||
- 抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。 | ||
|
||
- 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。 | ||
|
||
- 基本方法:是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种: | ||
|
||
- 抽象方法(Abstract Method) :一个抽象方法由抽象类声明、由其具体子类实现。 | ||
|
||
- 具体方法(Concrete Method) :一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。 | ||
|
||
- 钩子方法(Hook Method) :在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。 | ||
|
||
一般钩子方法是用于判断的逻辑方法,这类方法名一般为 isXxx,返回值类型为boolean类型。 | ||
|
||
- 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的组成步骤。 | ||
|
||
## 2 例子 | ||
|
||
打游戏有一般先初始化游戏、开始游戏、结束游戏。 | ||
|
||
```java | ||
public abstract class Game { | ||
public abstract void initialize(); | ||
|
||
public abstract void startPlay(); | ||
|
||
public abstract void endPlay(); | ||
|
||
//模板 | ||
public final void play() { | ||
//初始化游戏 | ||
initialize(); | ||
//开始游戏 | ||
startPlay(); | ||
//结束游戏 | ||
endPlay(); | ||
} | ||
} | ||
|
||
public class Honor extends Game { | ||
|
||
@Override | ||
void endPlay() { | ||
System.out.println("王者荣耀结束"); | ||
} | ||
|
||
@Override | ||
void initialize() { | ||
System.out.println("王者荣耀初始化"); | ||
} | ||
|
||
@Override | ||
void startPlay() { | ||
System.out.println("王者荣耀开始"); | ||
} | ||
} | ||
|
||
public class TestClient { | ||
public static void main(String[] args) { | ||
final Honor honor = new Honor(); | ||
honor.play(); | ||
} | ||
} | ||
``` | ||
|
||
## 3 优缺点 | ||
|
||
优点 | ||
|
||
- 提高代码复用性 | ||
|
||
将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中。 | ||
|
||
- 实现了反向控制 | ||
|
||
通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制 ,并符合“开闭原则”。 | ||
|
||
缺点 | ||
|
||
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。 | ||
- 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。 |
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,78 @@ | ||
## 1 概述 | ||
|
||
该模式**定义了一系列算法**,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。 | ||
|
||
策略模式的主要角色如下: | ||
|
||
- 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。 | ||
- 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。 | ||
- 环境(Context)类:持有一个策略类的引用,最终给客户端调用。 | ||
|
||
## 2 例子 | ||
|
||
百货公司在定年度的促销活动。针对不同的节日(春节、中秋节、圣诞节)推出不同的促销活动,由促销员将促销活动展示给客户。 | ||
|
||
```java | ||
//抽象策略 | ||
public interface Strategy { | ||
void show(); | ||
} | ||
|
||
//具体策略角色 | ||
//为春节准备的促销活动A | ||
public class StrategyA implements Strategy { | ||
public void show() { | ||
System.out.println("买一送一"); | ||
} | ||
} | ||
|
||
//为中秋准备的促销活动B | ||
public class StrategyB implements Strategy { | ||
public void show() { | ||
System.out.println("满200元减50元"); | ||
} | ||
} | ||
|
||
//为圣诞准备的促销活动C | ||
public class StrategyC implements Strategy { | ||
public void show() { | ||
System.out.println("满1000元加一元换购任意200元以下商品"); | ||
} | ||
} | ||
|
||
//环境角色(Context) | ||
public class SalesMan { | ||
//抽象策略角色的引用 | ||
private Strategy strategy; | ||
|
||
public SalesMan(Strategy strategy) { | ||
this.strategy = strategy; | ||
} | ||
|
||
//向客户展示促销活动 | ||
public void salesManShow(){ | ||
strategy.show(); | ||
} | ||
} | ||
``` | ||
|
||
## 3 优缺点 | ||
|
||
优点: | ||
|
||
- 策略类之间可以自由切换 | ||
|
||
由于策略类都实现同一个接口,所以使它们之间可以自由切换。 | ||
|
||
- 易于扩展 | ||
|
||
增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“ | ||
|
||
- 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。 | ||
|
||
缺点: | ||
|
||
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。 | ||
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。 | ||
|
||
|
Oops, something went wrong.