Compound mode-demo

The compound mode is to combine the previously learned modes to solve problems together. Compound mode usually combines two or more modes in a solution to solve the problem .

Below we use an example to illustrate the application of composite mode

1. We want to let a group of ducks bark, because barking is the behavior of ducks, and the calling of different ducks is different, so we create a public interface Quackable

package duck;

/**
 * 鸭子将实现这个接口,然后实现各自不同的叫声
 */
public interface Quackable
{
    public void quack();
}

2. Some ducks implement the Quackable interface

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. The simulator simulates duck calling

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();
    }
}
呱呱呱
呱呱呱
吱吱吱

So far so good. The above is a very simple example, but no pattern is used. Below we will gradually add some functions

We want to add some other animals, where there are ducks there will be geese, so we add a geese, geese cluck

package goose;

/**
 * 鹅类
 */
public class Goose
{
    public void honk()
    {
        System.out.println("咯咯咯");
    }
}

We added a goose class, he is not a duck type, so it is not a Quackable type, nor can it be passed into simulate (Quackable quackable)

We want to turn the goose into a duck type, so we can use the adapter mode to adapt it to a duck

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();
    }
}

Now that our simulator can use goose, we create the goose object and wrap it into the adapter to implement the Quackable interface so that we can continue

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();
    }
}

 simulate will call the quack () method of many objects, including the adapter's quack () method

呱呱呱
呱呱呱
吱吱吱
咯咯咯

Below we will have a new requirement to count the number of duck calls. How can it be done? We can create a decorator, and wrap the duck into the decorator object to give the duck new behavior (calculation count behavior). The advantage of this is that there is no need to modify the code inside the duck. This is the decorator pattern

Next we start to create a decorator

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;
    }
}

Emulator

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次

This duck call counter is great, but we found that many ducks are not counted, because these ducks are not packed, so they have no counting effect, this is the problem of the decoration mode! And every time you create an object, you must decorate one side, if you forget to decorate There is no statistical effect. So we plan to encapsulate the created and decorated parts, which requires the factory pattern

So next we need to create a factory, which is specifically responsible for creating decorated ducks. Since this factory needs to create different types of duck product families, we need to use the abstract factory pattern

First create an abstract factory

package factory;

import duck.Quackable;

/**
 * 我们定义一个抽象工厂,他们的子类会创建不同的家族
 */
public abstract class AbstractDuckFactory
{
    public abstract Quackable createMallardDuck();
    public abstract Quackable createRedheadDuck();
    public abstract Quackable createRubberDuck();
}

 Create the factories we really need, they are responsible for creating the decorated duck

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());
    }
}

Let's modify the simulator again

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();
    }
}

As the result of the last run, this time we can be sure that all the ducks have been decorated, because we are using the factory pattern and do not need to create objects ourselves 

呱呱呱
呱呱呱
吱吱吱
咯咯咯
鸭子总共叫了3次

This time the patrolman raised another question, why should we manage the ducks individually? If there are many ducks, it ’s messy

 So we need to think of these ducks as a collection, and the next time we order, we can let all the ducks act according to their orders, which is too convenient.

We need to treat collections as if they were a single object, which requires the use of composition patterns . Below we will create a composite class that needs to implement the same interface as the node element

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();
        }
    }
}

This time you do n’t need to pass in the node elements one by one, just pass the combination into the simulate () method

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();
    }
}

Completed the same effect, in the traversal of the combined object, we also used the iterator pattern

开始测试主群
呱呱呱
呱呱呱
吱吱吱
咯咯咯
鸭子总共叫了3次

Summary: What have we done?

A goose appeared, and it wanted to be like a Quackable, so we use the adapter mode to match the goose to the Quackable type. Now you can use the goose ’s adapter quack () method to make the goose cluck

Then the croaking scholar decided to count the number of croaking. Most of us used the decorator mode and added a decorator named QuackCounting. It is used to track the number of times quack () is called. And delegate the call to the object he decorated

But quackers worry that they forgot to add the Quackcounter decorator. So we use the abstract factory pattern to create ducks, put them in need of ducks, just ask the factory, and the factory will decorate the ducks for them.

It ’s a duck and a goose. We have management troubles, so we need a combination model to integrate many quackables into a group. We create a composite object. He also implements the interface quackable of the element object, making the user operate it like The operating elements are the same. So now the croak scientist can directly manipulate a collection, when iterating over it, use the iterator pattern

Published 138 original articles · praised 34 · 150,000 views

Guess you like

Origin blog.csdn.net/bbj12345678/article/details/105289839