大话设计模式-----(五)观察者模式、抽象工厂模式

观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

将一个系统分割成一系列相互协作的类 有一个很不好的副作用,那就是需要维护相关对象间的一致性。不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。

就是有点像老师要管理学生。
一个老师管理很多个学生。
明天上不上课,我要告诉所有学生。

把老师抽象

//抽象统治者 一般用一个抽象类或者一个接口实现

abstract class Subject{
    private List<Observer> observers = new ArrayList<Observer>(); 

    //增加学生

    public void Attach (Observer observer){
        observers.add(observer);
    }

    //通知
    public void Notify(){
        for (Observer o:observers){
            o.Update();
        }

    }

}

抽象学生

abstract class Observer{
    public abstract void Update();
}

具体老师

class ConcreteSubject extends Subject{

    private String subjectState;

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
    }



}

具体学生


class ConcreteObserver extends Observer{
    private String name;
    private String observerState;
    private ConcreteSubject subject;

    public ConcreteObserver(ConcreteSubject subject ,String name){
        this.subject = subject;
        this.name= name;
    }



    @Override
    public void Update() {
        // TODO Auto-generated method stub
        observerState = subject.getSubjectState();
        System.out.println("学生"+name+"的状态是"+observerState);
    }


    public ConcreteSubject getSubject() {
        return subject;
    }

    public void setSubject(ConcreteSubject subject) {
        this.subject = subject;
    }



}

客户端

public static void main(String[] args) {
        //同一个管理的类,增加要管理的人。然后统一设置属性。并显示
        ConcreteSubject s = new ConcreteSubject();
        s.Attach(new ConcreteObserver(s, "X"));
        s.Attach(new ConcreteObserver(s, "Y"));
        s.Attach(new ConcreteObserver(s, "Z"));
        s.setSubjectState("放假");
        s.Notify();


    }

这里写图片描述

一个对象改变同时需要改变其他对,而且不知道有多少对象有待改变时
观察者模式所做的工作就是接触耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不影响另一边的变化。

用老师和学生的例子不是很好。恩,就是像今天的计划安排是根据天气的。我们的计划安排看到天气改变那也会变。里面的具体很多。都会改变。

抽象工厂模式

最简单的例子就是写项目的数据库更换的话。要改很多代码。
但是用抽象工厂模式不用那么麻烦了。
比如两个表中都有一个表User()

对这个表的操作抽象出来。因为有两种不同的数据库。操作相同,但是具体的写法细节不同。

//User表的抽象

interface IUser{
    public void InsertBreakAction();
    public void GetUser();
}

因为有两个数据库那么就实现两个

//实现操作User表的数据库

class SqlserverUser implements IUser{

    @Override
    public void InsertBreakAction() {
        System.out.println("对User操作增加数据-----Sqlserver");

    }

    @Override
    public void GetUser() {
        System.out.println("对User操作获取数据-----Sqlserver");

    }



}
//数据库Access
class AccessUser implements IUser{

    @Override
    public void InsertBreakAction() {
        System.out.println("对User操作增加数据-----Access");

    }

    @Override
    public void GetUser() {
        System.out.println("对User操作获取数据-----Access");

    }



}

要创建这两个不同的数据库对User的操作就是创建两个小工厂

先抽象出工厂

//定义抽象工厂

interface IFactory{
    public  IUser CreateUser();

}

创建两个小工厂

//针对两个数据库创建两个具体的小工厂

//sqlserver

class SqlServerFactory implements IFactory{

    @Override
    public IUser CreateUser() {

        return new SqlserverUser();
    }

}

//access

class AccessFactory implements IFactory{

    @Override
    public IUser CreateUser() {
        // TODO Auto-generated method stub
        return new AccessUser();
    }



}

客户端

public static void main(String[] args) {

        IFactory iFactory = new AccessFactory();
        IUser iUser = iFactory.CreateUser();
            iUser.InsertBreakAction();
            iUser.GetUser();
    }

这里写图片描述

抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类

可以用简单工厂替换工厂方法。就是说做一个判断。
什么数据库那么就创建什么数据库工厂。然后客户端只需要调用就可以了。
但是这样要增加数据库还是要改switch语句。
可以利用反射来实现

所谓反射

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

举个栗子

定义个水果接口。子类有苹果和橘子。用到简单工厂的话。就要根据条件产生不同的子类。这就可以利用反射实现。

抽象水果

interface fruit{
    public abstract void eat();
}

两种水果

class Apple implements fruit{

    @Override
    public void eat() {
        System.out.println("Apple");

    }


}

class Orange implements fruit{

    @Override
    public void eat() {
        System.out.println("Orange");

    }



}

利用反射的工厂

class Factory{
     public static  fruit getInstance(String clssname) {
        fruit f = null;

        try {
        //Class.forName(传入需要的类名还有有包名).newInstance()
            f = (fruit)Class.forName(clssname).newInstance();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return f;
    }


}

主方法创建

    public static void main(String[] args) {
        fruit f = Factory.getInstance("test.Orange");
        f.eat();
    }

这里写图片描述

恩,就是说这个创建什么数据库是我们说的算的,因为定义的是字符变量。编译的时候编译的是变量。没有写死。读取配置文件。是什么数据库就创建什么就可以了。

恩,反射理解的不是很到位。最近也在看核心技术。早日读完。

新手理解可能不是很到位,若有错误望指出。

参考 http://www.cnblogs.com/lzq198754/p/5780331.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值