複合モードは、以前に学習したモードを組み合わせて問題を解決することです。複合モードは通常、2つ以上のモードを組み合わせて問題を解決します。
以下では、例を使用して複合モードのアプリケーションを説明します
1.カモの鳴き声はアヒルの振る舞いであり、異なるアヒルの呼び出しが異なるため、アヒルのグループに吠えさせたいので、パブリックインターフェイスQuackableを作成します。
package duck;
/**
* 鸭子将实现这个接口,然后实现各自不同的叫声
*/
public interface Quackable
{
public void quack();
}
2.いくつかのアヒルはクアッカブルインターフェイスを実装しています
package duck;
/**
* 绿头鸭
*/
public class MallardDuck implements Quackable {
@Override
public void quack() {
System.out.println("呱呱呱");
}
}
package duck;
/**
* 红头鸭
*/
public class RedheadDuck implements Quackable {
@Override
public void quack() {
System.out.println("呱呱呱");
}
}
package duck;
/**
* 橡皮鸭
*/
public class RubberDuck implements Quackable {
@Override
public void quack() {
System.out.println("吱吱吱");
}
}
3.シミュレーターはアヒルの鳴き声をシミュレートします
import duck.MallardDuck;
import duck.Quackable;
import duck.RedheadDuck;
import duck.RubberDuck;
import goose.Goose;
import goose.GooseAdapter;
public class Test
{
public static void main(String[] args) {
Test test = new Test();
test.go();
}
void go()
{
Quackable mallardDuck = new MallardDuck();
Quackable redheadDuck = new RedheadDuck();
Quackable rubberDuck = new RubberDuck();
simulate(mallardDuck);
simulate(redheadDuck);
simulate(rubberDuck);
}
void simulate(Quackable quackable)
{
quackable.quack();
}
}
呱呱呱
呱呱呱
吱吱吱
これまでのところ良い。上記は非常に単純な例ですが、パターンは使用されていません。以下にいくつかの機能を徐々に追加します
アヒルがいるところにガチョウがいる他の動物を追加したいので、ガチョウ、ガチョウの鳴き声を追加します
package goose;
/**
* 鹅类
*/
public class Goose
{
public void honk()
{
System.out.println("咯咯咯");
}
}
私たちはガチョウのクラスを追加しました。彼はアヒルのタイプではないため、クワッカブルのタイプではなく、シミュレート(クワッカブル、クワッカブル)に渡すこともできません。
ガチョウをアヒル型にしたいので、アダプターモードを使用してアヒルに適応させることができます
package goose;
import duck.Quackable;
/**
* 利用适配器,我们可以将鹅适配成鸭子
*/
public class GooseAdapter implements Quackable {
Goose goose;
/**
* 构造器传入需要适配的对象
* @param goose
*/
public GooseAdapter(Goose goose) {
this.goose = goose;
}
/**
* 当调用quack方法时,会被委托到鹅的honk方法
*/
@Override
public void quack() {
goose.honk();
}
}
シミュレーターがgooseを使用できるようになったので、gooseオブジェクトを作成してアダプターにラップし、Quackableインターフェースを実装して、続行できるようにします。
import duck.MallardDuck;
import duck.Quackable;
import duck.RedheadDuck;
import duck.RubberDuck;
import goose.Goose;
import goose.GooseAdapter;
public class Test
{
public static void main(String[] args) {
Test test = new Test();
test.go();
}
void go()
{
Quackable mallardDuck = new MallardDuck();
Quackable redheadDuck = new RedheadDuck();
Quackable rubberDuck = new RubberDuck();
//将鹅包装进适配器,就可以让鹅像鸭子一样,拥有鸭子的行为
Quackable goose = new GooseAdapter(new Goose());
simulate(mallardDuck);
simulate(redheadDuck);
simulate(rubberDuck);
//因为适配器是包装了鹅,并且实现了Quackable接口,所以能传入
simulate(goose);
}
void simulate(Quackable quackable)
{
quackable.quack();
}
}
シミュレートは、アダプタのquack()メソッドを含む多くのオブジェクトのquack()メソッドを呼び出します
呱呱呱
呱呱呱
吱吱吱
咯咯咯
以下に、ダックコールの数をカウントするための新しい要件があります。どうすればできますか?デコレータを作成し、アヒルをデコレータオブジェクトにラップして、アヒルに新しい動作(計算カウント動作)を与えることができます。これの利点は、アヒル内のコードを変更する必要がないことです。これはデコレータパターンです
次に、デコレータの作成を開始します
package decorator;
import duck.Quackable;
/**
* 统计鸭子叫声的装饰者
* 和适配器一样它要实现目标接口
*/
public class QuackCounter implements Quackable
{
Quackable duck; //被装饰的对象
static int count; //我们用静态变量来跟踪所有呱呱叫次数
//将被装饰的对象传入构造器中,并记录在实例变量中
public QuackCounter(Quackable duck) {
this.duck = duck;
}
/**
* 当quack()被调用时,叫声次数加一
*/
@Override
public void quack() {
duck.quack();
count++;
}
/**
* 返回所有在Quackable中发生的呱呱叫次数
* @return
*/
public static int getCount()
{
return count;
}
}
エミュレータ
import decorator.QuackCounter;
import duck.MallardDuck;
import duck.Quackable;
import duck.RedheadDuck;
import duck.RubberDuck;
import goose.Goose;
import goose.GooseAdapter;
public class Test
{
public static void main(String[] args) {
Test test = new Test();
test.go();
}
void go()
{
//每创建一个Quackable,就用一个新的装饰者包装它,我们只统计鸭子的叫声,所以不用装饰鹅
Quackable mallardDuck = new QuackCounter(new MallardDuck());
Quackable redheadDuck = new QuackCounter(new RedheadDuck());
Quackable rubberDuck = new QuackCounter(new RubberDuck());
//将鹅包装进适配器,就可以让鹅像鸭子一样,拥有鸭子的行为
Quackable goose = new GooseAdapter(new Goose());
simulate(mallardDuck);
simulate(redheadDuck);
simulate(rubberDuck);
//因为适配器是包装了鹅,并且实现了Quackable接口,所以能传入
simulate(goose);
//我们查看鸭子呱呱叫了几次
System.out.println("鸭子总共叫了" + QuackCounter.getCount()+"次");
}
/**
* 这里没有任何变动,被装饰和被适配的对象,还是Quackable类
* @param quackable
*/
void simulate(Quackable quackable)
{
quackable.quack();
}
}
呱呱呱
呱呱呱
吱吱吱
咯咯咯
鸭子总共叫了3次
このダックコールカウンターは素晴らしいですが、多くのアヒルはパックされていないため、カウントされないことがわかりました。これらのアヒルはカウント効果がなく、これは装飾モードの問題です!そして、オブジェクトを作成するたびに、装飾するのを忘れた場合は、片側を装飾する必要があります統計的な影響はありません。したがって、作成および装飾されたパーツをカプセル化することを計画しています。これには、ファクトリパターンが必要です。
次に、装飾されたアヒルの作成を担当するファクトリを作成する必要があります。このファクトリは、さまざまな種類のアヒル製品ファミリを作成する必要があるため、抽象的なファクトリパターンを使用する必要があります
最初に抽象ファクトリを作成します
package factory;
import duck.Quackable;
/**
* 我们定义一个抽象工厂,他们的子类会创建不同的家族
*/
public abstract class AbstractDuckFactory
{
public abstract Quackable createMallardDuck();
public abstract Quackable createRedheadDuck();
public abstract Quackable createRubberDuck();
}
私たちが本当に必要な工場を作る
package factory;
import decorator.QuackCounter;
import duck.MallardDuck;
import duck.Quackable;
import duck.RedheadDuck;
import duck.RubberDuck;
/**
* CountingDuckFactory扩展自抽象工厂,创建被装饰过的鸭子,它们具有统计的行为
*/
public class CountingDuckFactory extends AbstractDuckFactory {
@Override
public Quackable createMallardDuck() {
return new QuackCounter(new MallardDuck());
}
@Override
public Quackable createRedheadDuck() {
return new QuackCounter(new RedheadDuck());
}
@Override
public Quackable createRubberDuck() {
return new QuackCounter(new RubberDuck());
}
}
もう一度シミュレータを修正しましょう
import decorator.QuackCounter;
import duck.MallardDuck;
import duck.Quackable;
import duck.RedheadDuck;
import duck.RubberDuck;
import factory.AbstractDuckFactory;
import factory.CountingDuckFactory;
import goose.Goose;
import goose.GooseAdapter;
public class Test
{
public static void main(String[] args) {
Test test = new Test();
AbstractDuckFactory countingDuckFactory = new CountingDuckFactory();
test.go(countingDuckFactory);
}
void go(AbstractDuckFactory countingDuckFactory)
{
//每创建一个Quackable,就用一个新的装饰者包装它,我们只统计鸭子的叫声,所以不用装饰鹅
// Quackable mallardDuck = new QuackCounter(new MallardDuck());
// Quackable redheadDuck = new QuackCounter(new RedheadDuck());
// Quackable rubberDuck = new QuackCounter(new RubberDuck());
//现在可以利用工厂来创建鸭子对象了
Quackable mallardDuck = countingDuckFactory.createMallardDuck();
Quackable redheadDuck = countingDuckFactory.createRedheadDuck();
Quackable rubberDuck = countingDuckFactory.createRubberDuck();
//将鹅包装进适配器,就可以让鹅像鸭子一样,拥有鸭子的行为
Quackable goose = new GooseAdapter(new Goose());
simulate(mallardDuck);
simulate(redheadDuck);
simulate(rubberDuck);
//因为适配器是包装了鹅,并且实现了Quackable接口,所以能传入
simulate(goose);
//我们查看鸭子呱呱叫了几次
System.out.println("鸭子总共叫了" + QuackCounter.getCount()+"次");
}
/**
* 这里没有任何变动,被装饰和被适配的对象,还是Quackable类
* @param quackable
*/
void simulate(Quackable quackable)
{
quackable.quack();
}
}
前回の実行の結果として、今回はすべてのアヒルが装飾されていることを確認できます。これは、ファクトリパターンを使用しており、自分でオブジェクトを作成する必要がないためです。
呱呱呱
呱呱呱
吱吱吱
咯咯咯
鸭子总共叫了3次
今回パトロール士は別の質問をしました、なぜ私たちはアヒルを個別に管理する必要があるのですか?アヒルがたくさんいると面倒くさい
したがって、これらのアヒルをコレクションと考える必要があります。次に注文するときは、すべてのアヒルに彼らの注文に従って行動させることができます。
コレクションを単一のオブジェクトであるかのように扱う必要があります。これには、構成パターンを使用する必要があります。以下では、ノード要素と同じインターフェースを実装する必要がある複合クラスを作成します
package compose;
import duck.Quackable;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 创建鸭子组合类,操作这个组合就像和操作节点元素一样,所以它也和节点元素一样实现相同的接口
*/
public class Flock implements Quackable{
ArrayList quackers = new ArrayList();
/**
* 将节点元素记录到属于Flock的集合中
* @param quacker
*/
public void add(Quackable quacker)
{
quackers.add(quacker);
}
/**
* Flock也是Quackable,所以也具备quack()这个方法,此方法会对整个集合产生作用,
* 遍历ArrayList上的每一个元素上的quack()方法
*/
@Override
public void quack() {
Iterator<Quackable> iterator = quackers.iterator();
while (iterator.hasNext())
{
Quackable quacker = iterator.next();
quacker.quack();
}
}
}
今回は、ノード要素を1つずつ渡す必要はありません。組み合わせをSimulate()メソッドに渡すだけです。
import compose.Flock;
import decorator.QuackCounter;
import duck.MallardDuck;
import duck.Quackable;
import duck.RedheadDuck;
import duck.RubberDuck;
import factory.AbstractDuckFactory;
import factory.CountingDuckFactory;
import goose.Goose;
import goose.GooseAdapter;
public class Test
{
public static void main(String[] args) {
Test test = new Test();
AbstractDuckFactory countingDuckFactory = new CountingDuckFactory();
test.go(countingDuckFactory);
}
void go(AbstractDuckFactory countingDuckFactory)
{
//每创建一个Quackable,就用一个新的装饰者包装它,我们只统计鸭子的叫声,所以不用装饰鹅
// Quackable mallardDuck = new QuackCounter(new MallardDuck());
// Quackable redheadDuck = new QuackCounter(new RedheadDuck());
// Quackable rubberDuck = new QuackCounter(new RubberDuck());
//现在可以利用工厂来创建鸭子对象了
Quackable mallardDuck = countingDuckFactory.createMallardDuck();
Quackable redheadDuck = countingDuckFactory.createRedheadDuck();
Quackable rubberDuck = countingDuckFactory.createRubberDuck();
//将鹅包装进适配器,就可以让鹅像鸭子一样,拥有鸭子的行为
Quackable goose = new GooseAdapter(new Goose());
//创建组合元素Flock,然后把Quackable集合都放进去
Flock flock = new Flock();
flock.add(mallardDuck);
flock.add(redheadDuck);
flock.add(rubberDuck);
flock.add(goose);
//因为组合元素和节点元素都实现了共同接口,操作组合等同于操作节点元素
System.out.println("开始测试主群");
simulate(flock);
//我们查看鸭子呱呱叫了几次
System.out.println("鸭子总共叫了" + QuackCounter.getCount()+"次");
}
/**
* 这里没有任何变动,被装饰和被适配的对象,还是Quackable类
* @param quackable
*/
void simulate(Quackable quackable)
{
quackable.quack();
}
}
同じ効果を完了し、結合されたオブジェクトのトラバースで、イテレーターパターンも使用しました
开始测试主群
呱呱呱
呱呱呱
吱吱吱
咯咯咯
鸭子总共叫了3次
概要:何をしましたか?
ガチョウが現れ、クワッカブルのようになりたかったので、アダプタモードを使用して、ガチョウをクワッカブルタイプに一致させます。これで、ガチョウのアダプタのquack()メソッドを使用して、ガチョウを鳴らすことができます
その後、鳴き声を出す学者は、鳴き声の回数を数えることにしましたほとんどの人がデコレータモードを使用し、QuackCountingというデコレータを追加しました。quack()が呼び出された回数を追跡するために使用されます。そして、彼が装飾したオブジェクトへの呼び出しを委任
しかし、いじめっ子たちは、Quackcounterデコレータを追加するのを忘れたことを心配しています。したがって、私たちは抽象的なファクトリー・パターンを使用してアヒルを作成し、アヒルを必要とするように配置し、ファクトリーに尋ねるだけで、ファクトリーがアヒルを装飾します。
それはアヒルとガチョウです。管理上の問題があるため、多くのquackableをグループに統合するための組み合わせモデルが必要です。複合オブジェクトを作成します。また、要素オブジェクトのquackableインターフェースを実装し、ユーザーがそれを操作要素は同じです。だから、クロークの科学者はコレクションを直接操作できるようになりました。コレクションを反復するときは、イテレータパターンを使用します