デザインパターン 組み合わせパターン 注意事項
説明する
デザインパターン・組み合わせパターンの学習の書き方を記録します。使用される JDK バージョンはバージョン 1.8 です。
複合
目的: オブジェクトをツリー構造に結合して、「部分全体」の階層を表します。複合を使用すると、ユーザーは単一オブジェクトと複合オブジェクトを一貫して使用できるようになります。
構造:
で:
- コンポーネントは、コンポジション内のオブジェクトのインターフェイスを宣言します。必要に応じて、すべてのクラスに共通のインターフェイスのデフォルト動作を実装します。コンポーネントのサブコンポーネントにアクセスして管理するためのインターフェイスを宣言します。(オプション) アクセスのための再帰構造内のインターフェイスを定義します。親コンポーネントを作成し、必要に応じて実装します。
- Leaf は組み合わせのリーフ ノード オブジェクトを表し、リーフ ノードには子ノードはありません。プリミティブ オブジェクトの動作は組み合わせで定義されます。
- Composite は、サブコンポーネントを持つコンポーネントの動作を定義し、サブコンポーネントを保存し、サブコンポーネントに関連する操作を Component インターフェイスに実装します。
- クライアントは、コンポーネント インターフェイスを通じて複合コンポーネントのオブジェクトを操作します。
適用性:
- オブジェクトの部分全体の階層を表現したい。
- ユーザーが複合オブジェクトと単一オブジェクトの違いを無視し、複合構造内のすべてのオブジェクトを均一に使用することが望まれます。
利用シナリオ:
ツリー構造に応じて結合モードが生まれるため、ツリー構造が現れるのが結合モードの利用シナリオです。例: ファイル ディレクトリ表示、マルチレベル ディレクトリ表示、その他のツリー構造データ操作。
目次
組み合わせパターン例のクラス図
この UML クラス図を使用して、構成パターンの例を実装します。
メニューコンポーネントの抽象クラス
package com.example.deesign_patterns.composite;
//菜单组件类
public abstract class MenuComponent {
//菜单组件的名称
protected String name;
//菜单组件的层级
protected int level;
//添加子菜单
public void add(MenuComponent menuComponent){
throw new UnsupportedOperationException();
}
//移除子菜单
public void remove(MenuComponent menuComponent){
throw new UnsupportedOperationException();
}
//获取指定的子菜单
public MenuComponent getChild(int index){
throw new UnsupportedOperationException();
}
//获取菜单或者菜单项的名称
public String getName(){
return name;
}
//打印菜单名称的方法(包含子菜单和子菜单项)
public abstract void print();
}
メニューの種類
package com.example.deesign_patterns.composite;
import java.util.ArrayList;
import java.util.List;
//菜单类
public class Menu extends MenuComponent{
//菜单可以有多个子菜单或者子菜单项
private List<MenuComponent> menuComponentList=new ArrayList<MenuComponent>();
//构造方法
public Menu(String name,int level) {
this.name=name;
this.level=level;
}
@Override
public void add(MenuComponent menuComponent) {
menuComponentList.add(menuComponent);
}
@Override
public void remove(MenuComponent menuComponent) {
menuComponentList.remove(menuComponent);
}
@Override
public MenuComponent getChild(int index) {
return menuComponentList.get(index);
}
@Override
public void print() {
//打印菜单名称
for(int i=0;i<level;i++){
System.out.print("--");
}
System.out.println(name);
//打印子菜单或者子菜单项名称
for(MenuComponent component:menuComponentList){
component.print();
}
}
}
メニュー項目クラス
package com.example.deesign_patterns.composite;
//菜单项类
public class MenuItem extends MenuComponent{
//构造方法
public MenuItem(String name,int level) {
this.name=name;
this.level=level;
}
@Override
public void print() {
//打印菜单项的名称
for(int i=0;i<level;i++){
System.out.print("--");
}
System.out.println(name);
}
}
テストクラス
package com.example.deesign_patterns.composite;
//测试类
public class Client {
public static void main(String[] args) {
//创建菜单树
MenuComponent menu1=new Menu("菜单管理",2);
menu1.add(new MenuItem("页面访问",3));
menu1.add(new MenuItem("展开菜单",3));
menu1.add(new MenuItem("编辑菜单",3));
menu1.add(new MenuItem("删除菜单",3));
menu1.add(new MenuItem("新增菜单",3));
MenuComponent menu2=new Menu("权限配置",2);
menu2.add(new MenuItem("页面访问",3));
menu2.add(new MenuItem("提交保存",3));
MenuComponent menu3=new Menu("角色管理",2);
menu3.add(new MenuItem("页面访问",3));
menu3.add(new MenuItem("新增角色",3));
menu3.add(new MenuItem("修改角色",3));
//创建一级菜单
MenuComponent component=new Menu("系统管理",1);
//将二级菜单添加到一级菜单
component.add(menu1);
component.add(menu2);
component.add(menu3);
//打印菜单名称(如果有子菜单一块打印)
component.print();
}
}
利点:
- 結合モードでは、オブジェクトの階層のすべてまたは一部を表す、階層的な複雑なオブジェクトを明確に定義でき、クライアントは階層の違いを無視して、階層構造全体の制御を容易にできます。
- クライアントは、単一オブジェクトであるか複合オブジェクト全体であるかを気にすることなく、複合構造またはその中の単一オブジェクトを一貫して使用できるため、クライアント コードが簡素化されます。
- 既存のクラス ライブラリに変更を加えることなく、結合モードで新しいブランチ ノードとリーフ ノードを追加することが非常に便利です。これは、オープニングとクローズの原則に準拠します。
- 結合モードは、ツリー構造のオブジェクト指向実装に柔軟なソリューションを提供します。リーフ ノードとブランチ ノードを再帰的に組み合わせることで、複雑なツリー構造を形成できますが、ツリー構造の制御は非常に簡単です。