Skip to content

Latest commit

 

History

History
500 lines (384 loc) · 11.1 KB

6.装饰者模式和观察者模式.md

File metadata and controls

500 lines (384 loc) · 11.1 KB

装饰者模式

1.用于扩展一个类的功能或者 给一个类添加附加职责。

2.动态的给一个对象添加功能,这些功能可以再动态的撤销。

public abstract class Battercake {
    protected abstract String getMsg();

    protected abstract int getPrice();
}
public class BaseBattercake extends Battercake {
    @Override
    protected String getMsg() {
        return "煎饼";
    }

    @Override
    protected int getPrice() {
        return 5;
    }
}
public abstract class BattercakeDecorator extends Battercake {

    Battercake battercake;

    public BattercakeDecorator(Battercake battercake) {
        this.battercake = battercake;
    }

    @Override
    protected String getMsg() {
        return this.battercake.getMsg();
    }

    @Override
    protected int getPrice() {
        return this.battercake.getPrice();
    }
}
public class EggDecorator extends BattercakeDecorator{
    public EggDecorator(Battercake battercake) {
        super(battercake);
    }

    @Override
    protected String getMsg() {
        return super.getMsg() + "+1个鸡蛋";
    }

    @Override
    protected int getPrice() {
        return super.getPrice() + 1;
    }
}
public class SausageDecorator extends BattercakeDecorator{
    public SausageDecorator(Battercake battercake) {
        super(battercake);
    }

    @Override
    protected String getMsg() {
        return super.getMsg() + "+1根香肠";
    }

    @Override
    protected int getPrice() {
        return super.getPrice() + 2;
    }
}
public class BattercakeTest {
    public static void main(String[] args) {
        Battercake battercake;

        // 路边
        battercake = new BaseBattercake();

        //想加一个鸡蛋
        battercake = new EggDecorator(battercake);

        // 再加一个鸡蛋
        battercake = new EggDecorator(battercake);

        // 再加一根香肠
        battercake = new SausageDecorator(battercake);

        System.out.println(battercake.getMsg() + ",总价:" + battercake.getPrice());


    }
}

优点:

1.装饰者时继承的有力补充,比继承灵活,不改变原有对象的情况下动态的给一个对象扩展功能,即插即用。

2.通过使用不同装配类一级这些中装饰类的排列组合,可以实现不同效果。

3.装饰者完全遵守开闭原则。

缺点:

1.会出现更多的代码,更多的类,增加程序复杂性。

2.动态装饰时,多层装饰时会更复杂。

观察者模式

// 被观察者
public class GPer extends Observable {
    private String name = "GPer生态圈";
    private static GPer gper = null;

    public GPer() {
    }

    public static GPer getInstance() {
        if (null == gper) {
            gper = new GPer();
        }
        return gper;
    }

    public String getName() {
        return name;
    }

    public void publishQuestion(Question question) {
        System.out.println(question.getUseName() + "在" + this.name + "提交" + question.getContent());
        setChanged();
        notifyObservers(question);
    }
}
public class Question {
    private String useName;
    private String content;

    public String getUseName() {
        return useName;
    }

    public void setUseName(String useName) {
        this.useName = useName;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
// 观察者
public class Teacher implements Observer {

    private String name;

    public Teacher(String name) {
        this.name = name;
    }
    @Override
    public void update(Observable o, Object arg) {
        GPer g = (GPer) o;
        Question question = (Question) arg;
        System.out.println("==============================");
        System.out.println(name + "老师,您好:\n" + "您收到一个来自" + g.getName() + "的提问,希望您解答,问题内容如下:\n" +
                question.getContent() + "\n" + "提问者:" + question.getUseName());
    }
}
public class ObserverTest {
    public static void main(String[] args) {
        GPer gPer = GPer.getInstance();
        Teacher tom = new Teacher("Tom");
        Teacher mic = new Teacher("mic");

        Question question = new Question();
        question.setUseName("小明");
        question.setContent("观察者设计模式使用那些场景?");
        gPer.addObserver(tom);
        gPer.addObserver(mic);
        gPer.publishQuestion(question);
    }
}

观察者模式二

/**
 * 监听器的一种包装,标准事件源格式的定义
 */
public class Event {
    //事件源,事件是由谁发起的保存起来
    private Object source;
    //事件触发,要通知谁
    private Object target;
    //事件触发,要做什么动作,回调
    private Method callback;
    //事件的名称,触发的是什么事件
    private String trigger;
    //事件触发的时间
    private long time;

    public Event(Object target, Method callback) {
        this.target = target;
        this.callback = callback;
    }

    public Event setSource(Object source) {
        this.source = source;
        return this;
    }

    public Event setTime(long time) {
        this.time = time;
        return this;
    }

    public Object getSource() {
        return source;
    }

    public Event setTrigger(String trigger) {
        this.trigger = trigger;
        return this;
    }

    public long getTime() {
        return time;
    }

    public Object getTarget() {
        return target;
    }

    public Method getCallback() {
        return callback;
    }

    @Override
    public String toString() {
        return "Event{" + "\n" +
                "\tsource=" + source.getClass() + ",\n" +
                "\ttarget=" + target.getClass() + ",\n" +
                "\tcallback=" + callback + ",\n" +
                "\ttrigger='" + trigger + "',\n" +
                "\ttime=" + time + "'\n" +
                '}';
    }
}
/**
 * 监听器,它就是观察者
 */
public class EventLisenter {

    //JDK底层的Lisenter通常也是这样来设计的
    protected Map<String,Event> events = new HashMap<String,Event>();

    //事件名称和一个目标对象来触发事件
    public void addLisenter(String eventType,Object target){
        try {
            this.addLisenter(
                    eventType,
                    target,
                    target.getClass().getMethod("on" + toUpperFirstCase(eventType),Event.class));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void addLisenter(String eventType,Object target,Method callback){
        //注册事件
        events.put(eventType, new Event(target, callback));
    }


    //触发,只要有动作就触发
    private void trigger(Event event) {
        event.setSource(this);
        event.setTime(System.currentTimeMillis());

        try {
            //发起回调
            if(event.getCallback() != null){
                //用反射调用它的回调函数
                event.getCallback().invoke(event.getTarget(),event);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //事件名称触发
    protected void trigger(String trigger){
        if(!this.events.containsKey(trigger)){return;}
        trigger(this.events.get(trigger).setTrigger(trigger));
    }

    //逻辑处理的私有方法,首字母大写
    private String toUpperFirstCase(String str){
        char[] chars = str.toCharArray();
        chars[0] -= 32;
        return String.valueOf(chars);
    }
}
public class Keybord extends EventLisenter {

    public void down(){

    }

    public void up(){

    }

}
public interface MouseEventType {
    //单击
    String ON_CLICK = "click";

    //双击
    String ON_DOUBLE_CLICK = "doubleClick";

    //弹起
    String ON_UP = "up";

    //按下
    String ON_DOWN = "down";

    //移动
    String ON_MOVE = "move";

    //滚动
    String ON_WHEEL = "wheel";

    //悬停
    String ON_OVER = "over";

    //失焦
    String ON_BLUR = "blur";

    //获焦
    String ON_FOCUS = "focus";
}
public class Mouse extends EventLisenter {

    public void click(){
        System.out.println("调用单击方法");
        this.trigger(MouseEventType.ON_CLICK);
    }

    public void doubleClick(){
        System.out.println("调用双击方法");
        this.trigger(MouseEventType.ON_DOUBLE_CLICK);
    }

    public void up(){
        System.out.println("调用弹起方法");
        this.trigger(MouseEventType.ON_UP);
    }

    public void down(){
        System.out.println("调用按下方法");
        this.trigger(MouseEventType.ON_DOWN);
    }

    public void move(){
        System.out.println("调用移动方法");
        this.trigger(MouseEventType.ON_MOVE);
    }

    public void wheel(){
        System.out.println("调用滚动方法");
        this.trigger(MouseEventType.ON_WHEEL);
    }

    public void over(){
        System.out.println("调用悬停方法");
        this.trigger(MouseEventType.ON_OVER);
    }

    public void blur(){
        System.out.println("调用获焦方法");
        this.trigger(MouseEventType.ON_BLUR);
    }

    public void focus(){
        System.out.println("调用失焦方法");
        this.trigger(MouseEventType.ON_FOCUS);
    }
}
public class MouseEventCallback {

    public void onClick(Event e){
        System.out.println("===========触发鼠标单击事件==========" + "\n" + e);
    }

    public void onDoubleClick(Event e){
        System.out.println("===========触发鼠标双击事件==========" + "\n" + e);
    }

    public void onUp(Event e){
        System.out.println("===========触发鼠标弹起事件==========" + "\n" + e);
    }

    public void onDown(Event e){
        System.out.println("===========触发鼠标按下事件==========" + "\n" + e);
    }

    public void onMove(Event e){
        System.out.println("===========触发鼠标移动事件==========" + "\n" + e);
    }

    public void onWheel(Event e){
        System.out.println("===========触发鼠标滚动事件==========" + "\n" + e);
    }

    public void onOver(Event e){
        System.out.println("===========触发鼠标悬停事件==========" + "\n" + e);
    }

    public void onBlur(Event e){
        System.out.println("===========触发鼠标失焦事件==========" + "\n" + e);
    }

    public void onFocus(Event e){
        System.out.println("===========触发鼠标获焦事件==========" + "\n" + e);
    }

}
public class MouseEventTest {
    public static void main(String[] args) {

        MouseEventCallback callback = new MouseEventCallback();

        Mouse mouse = new Mouse();

        //@谁?  @回调方法
        mouse.addLisenter(MouseEventType.ON_CLICK,callback);
        mouse.addLisenter(MouseEventType.ON_FOCUS,callback);

        mouse.click();

        mouse.focus();


    }
}