【达内课程】设计模式


设计模式:对特定问题的解决方案

单例模式

解决问题

一个类只能创建一个实例,例如MyApplication、SocketConnection

解决方案

private构造方法,static newInstance()返回类本身

普通程序

在Eclipse中新建一个MyApplication.java

public class MyApplication {
	public MyApplication(){
		System.out.println(this.toString()+"构造方法");
	}
}

Main.java

public class Main {
	public static void main(String[] args){
		for(int i=0;i<10;i++){
			MyApplication application = new MyApplication();
		}
	}
}

查看输出,可以看到新建了10个MyApplication对象

MyApplication@15db9742构造方法
MyApplication@6d06d69c构造方法
......
MyApplication@42a57993构造方法

改为单例模式

MyApplication.java

public class MyApplication {
	private static MyApplication instance;
	
	public static MyApplication newInstance(){
		if(instance == null){
			instance = new MyApplication();
		}
		return instance;
	}
	
	private MyApplication(){
		System.out.println(this.toString()+"构造方法");
	}
}

Main.java

public class Main {
	public static void main(String[] args){
		for(int i=0;i<10;i++){
			MyApplication application = MyApplication.newInstance();
		}
	}
}

运行,查看输出,可以看到只创建了一个MyApplication对象

MyApplication@15db9742构造方法

做些不同尝试:
Main.java中的程序改为

public class Main {
	public static void main(String[] args){
		new Thread(){
			public void run(){
				for(int i=0;i<10;i++){
					MyApplication application = MyApplication.newInstance();
				}
			}
		}.start();
	}
}

查看输出

MyApplication@6426ac69构造方法

Main.java改为

public class Main {
	public static void main(String[] args){	
		for(int i=0;i<10;i++){
			new Thread(){
				public void run(){
					MyApplication application = MyApplication.newInstance();
				}
			}.start();
		}
	}
}

查看输出,不一定次数的构造方法

tarena.day0101.MyApplication@381037cd构造方法
tarena.day0101.MyApplication@10b7ce35构造方法
tarena.day0101.MyApplication@5895a81c构造方法
tarena.day0101.MyApplication@4a8f0963构造方法
tarena.day0101.MyApplication@44ea4bd2构造方法
tarena.day0101.MyApplication@407e3dad构造方法

为什么不是一个构造方法呢?怎样保证多个线程也创建一个MyApplication呢?改为

public class MyApplication {
	private static MyApplication instance;
	//synchronized前面的线程执行完,后边的线程才会执行
	//不加,就是多个线程同时执行这个方法
	public synchronized static MyApplication newInstance(){
		if(instance == null){
			instance = new MyApplication();
		}
		return instance;
	}
	
	private MyApplication(){
		System.out.println(this.toString()+"构造方法");
	}
}

再次运行,查看输出

MyApplication@6426ac69构造方法

工厂设计模式

解决问题

创建对象时,解耦合

解决方案

使用对象的地方调工厂返回的接口

普通程序

在这里插入图片描述

public class LoginByUserBiz {
	public boolean login(Object object){
		System.out.println("LoginByUserBiz-login()");
		return true;
	}
}
public class LoginView {
	public static void main(String[] args){	
		//直接创建对象,耦合高,一个地方改,其他地方都要改
		LoginByUserBiz biz = new LoginByUserBiz();
		biz.login(null);
	}
}

查看输出

LoginByUserBiz-login()

改为工厂设计模式

创建ILoginBiz

public interface ILoginBiz {
	public boolean login(Object object);
}

创建LoginBySmsBiz并实现这个接口

public class LoginBySmsBiz implements ILoginBiz{
	public boolean login(Object object){
		System.out.println("LoginBySmsBiz-login()");
		return true;
	}
}

刚才的LoginByUserBiz也实现这个接口

public class LoginByUserBiz implements ILoginBiz{
	public boolean login(Object object){
		System.out.println("LoginByUserBiz-login()");
		return true;
	}
}

现在创建工厂Factory

public class Factory {
	public static ILoginBiz Instance(){
		return new LoginByUserBiz();
	}
}

LoginView

public class LoginView {
	public static void main(String[] args){	
		//调接口,解耦合,耦合低
		ILoginBiz iLoginBiz = Factory.newInstance();
		iLoginBiz.login(null);
	}
}

查看输出

LoginByUserBiz-login()

如果现在需要换sms登录,那么我们只需要修改Factory

public class Factory {
	public static ILoginBiz newInstance(){
		//return new LoginByUserBiz();
		return new LoginBySmsBiz();
	}
}

查看输出

LoginBySmsBiz-login()

观察者设计模式

解决问题

下一层Biz层的数据发生变化,上一层View层要知道

解决方案

目标(下一层Biz层)发生变化,调观察者(接口)

观察者设计模式程序

创建接口Observer

//定义每个观察者要实现的功能
public interface Observer {
    public String save();
}

创建三个观察者,都实现Observer接口

public class Wukong implements Observer {
    @Override
    public String save() {
        return "Wukong来了";
    }
}
public class Bajie implements Observer {
    @Override
    public String save() {
        return "Bajie来了";
    }
}

public class Shaseng implements Observer {
    @Override
    public String save() {
        return "Shaseng来了";
    }
}

创建目标

//目标
public class Tangseng {
    ArrayList<Observer> observerArrayList = new ArrayList<>();

    public void register(Observer observer){
        observerArrayList.add(observer);
    }

    //目标发生变化,调用观察者
    public ArrayList<String> help(){
        ArrayList<String> stringArrayList = new ArrayList<>();
        for(Observer observer:observerArrayList){
            String string = observer.save();
            stringArrayList.add(string);
        }
        return stringArrayList;
    }
}

创建界面,点击按钮需要展示通知三个徒弟
在这里插入图片描述
MainActivity

public class MainActivity extends AppCompatActivity {
    private Button button;
    private ListView listView;

    //目标
    Tangseng tangseng;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //创建三个观察者
        Wukong wukong = new Wukong();
        Bajie bajie = new Bajie();
        Shaseng shaseng = new Shaseng();

        tangseng = new Tangseng();
        tangseng.register(wukong);
        tangseng.register(bajie);
        tangseng.register(shaseng);

        button = findViewById(R.id.btn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                test();
            }
        });

        listView = findViewById(R.id.listView);
    }

    private void test() {
        ArrayList<String> arrayList = tangseng.help();
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_expandable_list_item_1, arrayList);
        listView.setAdapter(arrayAdapter);
    }
}

装饰模式

概念

装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

特点

(1) 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
(2) 装饰对象包含一个真实对象的引用(reference)
(3) 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
(4) 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

适用条件

以下情况使用Decorator模式

(1)需要扩展一个类的功能,或给一个类添加附加职责。
(2)需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
(3)需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
(4)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

优点

(1)Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
(2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点

(1)这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
(2)装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

代码中的应用

IO流的操作就是典型的装饰模式

举个栗子

创建装饰模式公共接口IPerson

/**
 * 装饰模式公共接口
 */
public interface IPerson {
    void desc();
}

创建被装饰类 Errol

/**
 * 被装饰类
 */
public class Errol implements IPerson{
    @Override
    public void desc() {
        Log.d("TTT","Errol是一个人");
    }
}

创建装饰器,通过装饰器来装饰 Errol。装饰器和被装饰类要实现同一个公共接口,同时装饰器中需要持有被装饰类,被装饰类以公共接口的方式接收,这样的好处是可以通过不同的装饰组合出现不同的对象

/**
 * 装饰器
 */
public class PersonDecorator implements IPerson{
    /**
     * 持有被装饰类,以公共接口接收
     */
    IPerson iPerson;
    public PersonDecorator(IPerson iPerson){
        this.iPerson = iPerson;
    }

    @Override
    public void desc() {
        iPerson.desc();
    }
}

现在需要创建不同的装饰子类,真正的装饰内容在装饰子类中实现

/**
 * 装饰子类
 */
public class SmartPerson extends PersonDecorator {
    public SmartPerson(IPerson iPerson) {
        super(iPerson);
    }

    @Override
    public void desc() {
        super.desc();
        Log.d("TTT","是一个聪明的人");
    }
}

测试一下

		IPerson iPerson = new Errol();
        iPerson.desc();
        iPerson = new SmartPerson(new Errol());
        iPerson.desc();

D/TTT: Errol是一个人
D/TTT: Errol是一个人
D/TTT: 是一个聪明的人

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值