天天看点

【设计模式】——23种设计模式——核心设计模式(含理解+代码)【3】

设计模式——拜访者模式

基本理解

拜访者模式的本质就是,对于同一个对象而言,访问者的角色不一样,所看到的数据就不一样, 比如,对于员工数据而言,如果是CEO访问者角色则关注的数据跟CFO访问者角色所关注的数据是不一样的;

基本意义

一般来讲,一个对象有大量的数据组合需要会频繁访问就会出现某些访问者与被访问组合的规律,如果能从中抽象出一个访问类型对应访问逻辑,那么就可以提高代码的维护性,将访问类型和访问逻辑统一维护;

定义拜访者实现——以区分不同角色对象的访问逻辑

public interface Visitor {
    void visit(Engineer engineer);// 访问工程师类型
    void visit(Manager manager);// 访问经理类型
}

```java
public class CTOVisitor implements Visitor {
    @Override
    public void visit(Engineer engineer) {
        System.out.println("工程师: " + engineer.name + ", 代码行数: " + engineer.getCodeLines());
    }

    @Override
    public void visit(Manager manager) {
        System.out.println("经理: " + manager.name + ", 产品数量: " + manager.getProducts());
    }
}

```java
public class CEOVisitor implements Visitor {
    @Override
    public void visit(Engineer engineer) {
        System.out.println("工程师: " + engineer.name + ", KPI: " + engineer.kpi);
    }

    @Override
    public void visit(Manager manager) {
        System.out.println("经理: " + manager.name + ", KPI: " + manager.kpi +
                ", 新产品数量: " + manager.getProducts());
    }
}

           

定义数据元被访问的逻辑——以区分不同数据对象的展示的内容

public abstract class Staff {

    public String name;
    public int kpi;// 员工KPI

    public Staff(String name) {
        this.name = name;
        kpi = new Random().nextInt(10);
    }
    // 核心方法,接受Visitor的访问
    public abstract void accept(Visitor visitor);
}
public class Engineer extends Staff {

    public Engineer(String name) {
        super(name);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    // 工程师一年的代码数量
    public int getCodeLines() {
        return new Random().nextInt(10 * 10000);
    }
}
public class Manager extends Staff {

    public Manager(String name) {
        super(name);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    // 一年做的产品数量
    public int getProducts() {
        return new Random().nextInt(10);
    }
}

           

定义批量数据

public class BusinessReport {
    private List<Staff> mStaffs = new LinkedList<>();
    public BusinessReport() {
        mStaffs.add(new Manager("经理-ComponetElement"));
        mStaffs.add(new Engineer("工程师-ComponetElement"));
        mStaffs.add(new Engineer("工程师-B"));
        mStaffs.add(new Engineer("工程师-C"));
        mStaffs.add(new Manager("经理-B"));
        mStaffs.add(new Engineer("工程师-D"));
    }

    /**
     * 为访问者展示报表
     * @param visitor 公司高层,如CEO、CTO
     */
    public void showReport(Visitor visitor) {
        for (Staff staff : mStaffs) {
            staff.accept(visitor);
        }
    }
}
           

测试

public class _Test01 {
    public static void main(String[] args) {
        /**
         * @商务报表类
         * 包含了需要被访问的所有数据
         */
        BusinessReport report = new BusinessReport();
        /**
         * @角色匹配
         * 传入不同或实现不同实现的接口,能看到的数据是不一样的
         */
        report.showReport(new CEOVisitor());
        report.showReport(new CTOVisitor());
    }
}

           
针对于拜访者模式,显然是一个新增了角色则需要新增一个访问者实现类,如果新增了数据对象则需要在拜访者接口新增一行接口方法

设计模式——外观模式(设计思想——针对组件的交互)

这个设计模式,主要是隐藏系统的内部的复杂,对外暴露用户关注的方法,

而不是让外部用户一步步已经完成细节调用

;就就好你去银行办事,只需要写一个申请书就可以完成一些列复杂的大额转账流程,而不需要自己亲自去调用银行该做的事情,代码也是一样不需要自己亲自调用内部函数的细节,这样也降低了耦合度,

一些列流程处理的组合,减少细节碰撞,互相知道的越少越好

设计模式——组合模式(设计思想——针对同类差异化)

组合模式只是父类抽共性的一种表现,常见于同一层次的数据元,但可能存在细微差异的情况,比如树形结构数据中,如果所有树形节点可能存在微小差异,我们一般也是抽共性看成同一个节点对待(共同一个抽象类或接口),内部自由实现不同的东西

一致性父类

父类保存了各个节点的一致性
static abstract class Component {
        protected String name;
        public Component(String name) {
            this.name = name;
        }
        public abstract String operation();
        public boolean addChild(Component component) {
            throw new UnsupportedOperationException("addChild not supported!");
        }
        public boolean removeChild(Component component) {
            throw new UnsupportedOperationException("removeChild not supported!");
        }
        public Component getChild(int index) {
            throw new UnsupportedOperationException("getChild not supported!");
        }
    }
           

实现类

/**
     * @非子节点
     */
    static class Composite extends Component {
        private List<Component> mComponents;
        public Composite(String name) {
            super(name);
            this.mComponents = new ArrayList<>();
        }
        @Override

        public String operation() {
            StringBuilder builder = new StringBuilder(this.name);
            for (Component component : this.mComponents) {
                builder.append("\n");
                builder.append(component.operation());
            }
            return builder.toString();
        }
        @Override
        public boolean addChild(Component component) {
            return this.mComponents.add(component);
        }
        @Override
        public boolean removeChild(Component component) {
            return this.mComponents.remove(component);
        }
        @Override
        public Component getChild(int index) {
            return this.mComponents.get(index);
        }
    }
    /**
     * @叶子节点操作
     */
    static class Leaf extends Component {
        public Leaf(String name) {
            super(name);
        }
        @Override
        public String operation() {
            return this.name;
        }
    }
           

测试

public static void main(String[] args) {
        // 来一个根节点
        Component root = new Composite("root");
        // 来一个树枝节点
        Component branchA = new Composite("---branchA");
        Component branchB = new Composite("------branchB");
        // 来一个叶子节点
        Component leafA = new Leaf("------leafA");
        Component leafB = new Leaf("---------leafB");
        Component leafC = new Leaf("---leafC");

        root.addChild(branchA);
        root.addChild(leafC);
        branchA.addChild(leafA);
        branchA.addChild(branchB);
        branchB.addChild(leafB);

        String result = root.operation();
        System.out.println(result);
}
           

设计模式——状态模式

基本意义

类的行为是基于它的状态改变的

最简单的状态模式

给定几个if else 然后做状态判断改变行为模式
public class _Test01 {
    static public class Hero {
        public static final int COMMON = 1;//正常状态
        public static final int SPEED_UP = 2;//加速状态
        public static final int SPEED_DOWN = 3;//减速状态
        public static final int SWIM = 4;//眩晕状态
        private int state = COMMON;//默认是正常状态
        public void setState(int state) {
            this.state = state;
        }
        public void run() {
            new Thread(){
                public void run(){
                    try {
                        while (true){
                            if (state == SPEED_UP) {
                                System.out.println("--------------加速跑动---------------");
                            }else if (state == SPEED_DOWN) {
                                System.out.println("--------------减速跑动---------------");
                            }else if (state == SWIM) {
                                System.out.println("--------------不能跑动---------------");
                            }else {
                                System.out.println("--------------正常跑动---------------");
                            }
                            Thread.sleep(500);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }.start();
        }

    }

    public static void main(String[] args)  throws Exception {
        Hero hero=new Hero();
        hero.run();
        hero.setState(Hero.SPEED_UP);
        Thread.sleep(2000);
        hero.setState(Hero.SPEED_DOWN);
        Thread.sleep(2000);
        hero.setState(Hero.SWIM);
        hero.setState(Hero.COMMON);

    }
}
           

状态模式——实现类方法

显然利用单值做状态判断不利于扩展,所以利用状态对象来实现状态行为是可取之举
public class StateContext {
    public static final RunState COMMON = new CommonState();
    public static final RunState SPEED_UP =  new SpeedUpState();
    public static final RunState SPEED_DOWN = new SpeedDownState();
    public static final RunState SWIM = new SwimState();//眩晕状态
    public static interface RunState {
        void run(Hero hero);
    }
    public static class CommonState implements RunState{
        public void run(Hero hero) {
            System.out.println("--------------正常跑动---------------");
        }
    }
    public static class SpeedUpState  implements RunState{

        public void run(Hero hero) {
            System.out.println("--------------加速跑动---------------");
        }
    }
    public static class SpeedDownState  implements RunState{

        public void run(Hero hero) {
            System.out.println("--------------减速跑动---------------");
        }
    }
    public static class SwimState   implements RunState {
        public void run(Hero hero) {
            System.out.println("--------------正常跑动---------------");
        }
    }
}
           
public class Hero {
    StateContext.RunState state=new StateContext.CommonState();

    public void run() {
        Hero hero=this;
        new Thread(){
            public void run(){
                try {
                    while (true){
                        state.run(hero);
                        Thread.sleep(500);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public void setState(StateContext.RunState state){
        this.state=state;
    }
}
           
public class _Test02 {
public static void main(String[] args)  throws Exception {
        Hero hero=new Hero();
        hero.run();`在这里插入代码片`
        hero.setState(StateContext.SPEED_UP);
        Thread.sleep(2000);
        hero.setState(StateContext.SPEED_DOWN);
        Thread.sleep(2000);
        hero.setState(StateContext.SWIM);

    }
}

           

状态模式——枚举方法

显然过多的实现类也不好看,所以利用枚举处理函数是最直接的,又比哈希还好,固定情况下枚举比哈希好
public  interface  RunState {
    void run(Hero hero);
}
           

统一集中维护处理函数,比那种太多实现类好很多

public enum  StateEnum {
    COMMON("COMMON", "正常速度", new RunState() {
        public void run(Hero hero) {
            System.out.println("--------------正常跑动---------------");
        }
    }),
    SPEED_UP("SPEED_UP","加速", new RunState() {
        public void run(Hero hero) {
            System.out.println("--------------加速跑动---------------");
        }
    }),
    SPEED_DOWN("SPEED_DOWN","减速", new RunState() {
        public void run(Hero hero) {
            System.out.println("--------------减速跑动---------------");
        }
    }),
    SWIM("SWIM","眩晕", new RunState() {
        public void run(Hero hero) {
                System.out.println("--------------正常跑动---------------");
        }
    });
    private final String key;
    private final String value;
    private final RunState function;

    public String getKey() {
        return key;
    }
    public String getValue() {
        return value;
    }
    public void run(Hero hero){
        function.run(hero);
    }
    StateEnum(String key, String value,RunState function) {
        this.key = key;
        this.value = value;
        this.function=function;
    }
}

           
public class Hero {
    StateEnum state=StateEnum.COMMON;
    public void run() {
     Hero hero=this;
        new Thread(){
            public void run(){
                try {
                    while (true){
                        state.run(hero);
                        Thread.sleep(500);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public void setState(StateEnum state){
        this.state=state;
    }
}

           
public class _Test03 {
    public static void main(String[] args)  throws Exception {
        Hero hero=new Hero();
        hero.run();
        hero.setState(StateEnum.COMMON);
        Thread.sleep(2000);
        hero.setState(StateEnum.SPEED_DOWN);
        Thread.sleep(2000);
        hero.setState(StateEnum.SWIM);
    }
}
           

设计模式——中介者模式

中介者模式是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,这个类就来处理不同类之间的通讯

简单中介者

这个只能解决统一用一个中介工具类去管理函数
public class User {
    private String name;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public User (String name) {
        this.name = name;
    }

    public void sendMessage (String message) {
        StudyGroup.showMessage(this, message);
    }
}
public class StudyGroup {
    public static void showMessage (User user, String message) {
        System.out.println(new Date().toString() + " [" + user.getName() + "] :" + message);
    }
}
public class Test {
    public static void main(String[] args) {
        User ko = new User("K.O");
        User tom = new User("Tom");
        ko.sendMessage("learn design pattern.");
        tom.sendMessage("ok!");
    }
}
           

复杂中介者

中介者管理了利用哈希结构管辖指定元素引用存储,所有外部对象与某个组件通讯必须指定key把自己传过来

所有组件为了实现规范的通讯必须统一实现通讯接口,规范外部调用方法以及内部封装的MetaData制定好

通讯范式接口/与中介者处理接口

/* 
   规范组件之间通讯范式
 */
@Data
public abstract  class ComponetElement {
    protected ReportMediator mediator;
    protected ComponetMetaData componetMetaData;

    public abstract void receive(ComponetElement componetElement);//接受消息
    public abstract void send(String key);//发送消息
    public void setMediator(ReportMediator mediator) {
        this.mediator = mediator;
    }
}
/* 
   规范中介者的接口逻辑
 */
public abstract class Mediator {
    protected Map<String,ComponetElement> elementMap=new ConcurrentHashMap<>();
    abstract void register(String key,ComponetElement colleague);
    abstract void relay(String key,ComponetElement colleague);
}
/* 
   每个组件的核心数据
 */
@Data
public   class ComponetMetaData {
   String serviceName;
}
           

中介者实现类

public class ReportMediator  extends Mediator{
    @Override
    void register(String key,ComponetElement colleague) {
       elementMap.put(key,colleague);
        colleague.setMediator(this);
    }
    @Override
    void relay(String key,ComponetElement colleague) {
        ComponetElement componetElement = elementMap.get(key);
        if(componetElement!=null){
            componetElement.receive(colleague);
        };
    }
}

           

组件对象实现类

public class ServiceOneComponet extends ComponetElement {
    public ServiceOneComponet(){
        this.componetMetaData=new ComponetMetaData();
        this.componetMetaData.setServiceName("ServiceOneComponet");
    }
    @Override
    public void receive(ComponetElement componetElement) {
        System.out.println(this.getComponetMetaData().getServiceName()+"接受到了"+componetElement.getComponetMetaData().getServiceName()+"的通讯");
    }
    public void send(String key) {
        super.mediator.relay(key,this);
    }
}
           
public class ServiceTwoComponet extends ComponetElement {

    public ServiceTwoComponet(){
        this.componetMetaData=new ComponetMetaData();
        this.componetMetaData.setServiceName("ServiceTwoComponet");
    }
    @Override
    public void receive(ComponetElement componetElement) {
        System.out.println(this.getComponetMetaData().getServiceName()+"接受到了"+componetElement.getComponetMetaData().getServiceName()+"的通讯");

    }
    public void send(String key) {
        super.mediator.relay(key,this);
    }
}
           
public class ServiceThreeComponet extends ComponetElement {
    public ServiceThreeComponet(){
        this.componetMetaData=new ComponetMetaData();
        this.componetMetaData.setServiceName("ServiceThreeComponet");
    }
    @Override
    public void receive(ComponetElement componetElement) {
        System.out.println(this.getComponetMetaData().getServiceName()+"接受到了"+componetElement.getComponetMetaData().getServiceName()+"的通讯");
    }

    public void send(String key) {
        super.mediator.relay(key, this);
    }
}
           

测试

public class _Test01 {
    private final  static String SERVER_COMPONET_ONE="SERVER_COMPONET_ONE";
    private final  static String SERVER_COMPONET_TWO="SERVER_COMPONET_TWO";
    private final  static String SERVER_COMPONET_THREE="SERVER_COMPONET_THREE";
    public static void main(String[] args) {
        ReportMediator reportMediator =new ReportMediator();
        ServiceOneComponet serviceOneComponetOne = new ServiceOneComponet();
        ServiceOneComponet serviceOneComponetTwo = new ServiceOneComponet();
        ServiceOneComponet serviceOneComponetThree = new ServiceOneComponet();
        reportMediator.register(SERVER_COMPONET_ONE,serviceOneComponetOne);
        reportMediator.register(SERVER_COMPONET_TWO,serviceOneComponetTwo);
        reportMediator.register(SERVER_COMPONET_THREE,serviceOneComponetThree);
        /*
         这段代码一般都在类内部调用自动完成通讯,基于外观模式在内部完成,但我们为了方便就在外部调用了
          */
        serviceOneComponetOne.send(SERVER_COMPONET_THREE);
    }
}

           
这种中介者模式缺点也显而易见,就是根本无法清除究竟有多少个组件是被管理的,究竟一个组件会和多少组件完成通讯,如果为了实现更大类的差异化,则可能需要定义更通用的访问规则

设计模式——备忘录模式

设计模式——空对象模式

设计模式——原型工厂模式

设计模式——代理模式

设计模式——解释器模式