初学的几种设计模式
单例设计模式
什么是单例: 在程序运行,一个类只需要一个实例,不能出现多个实例,就叫单例。
单例的模式动机: 在一个系统或平台中,某个类的实例(对象),只需要有一个 一个朝代只能有一个皇帝,一个公司只能有一个老板
原理: 得到一个类的对象,需要通过new关键字,调用构造方法创建对象
需要完成的事项:
1)私有化构造方法;
2)在类内创建对象;
3)提供一个共有的方法,用来获取本类对象
#饿汉式
public class Boss{
//属性
private String name;
private int age;
//私有化构造方法
private Boss(String name, int age){
this.name = name;
this.age = age; }
//私有静态本类对象作为属性
private static Boss boss = new Boss("马云",12);
//提供共有静态方法获取本类对象
public static Boss getBoss(){
return boss;
}
}
#懒汉式
public class Boss{
private String name;
private int age;
//私有构造方法
private King(String name, int age){
this.name = name;
this.age = age; }
//私有静态本类对象
private static King king;
//共有静态方法获取本类对象
public static King getKing(){
if(king==null){
king = new King("唐太宗",12);
}
return king;
}
}
简单工厂设计模式
简单工厂解决创建对象的问题。
1.原理:多态
生活中的工厂:手机厂,电视厂,服装厂…
2.动机:
考虑一个简单的软件应用场景,一个软件系统可以提供多个外观不同的按钮(如圆形按钮、矩形按钮、菱形 按钮等),这些按钮都源自同一个基类,不过在继承基类后不同的子类修改了部分属性从而使得它们可以呈 现不同的外观,如果我们希望在使用这些按钮时,不需要知道这些具体按钮类的名字,只需要知道表示该按 钮类的一个参数,并提供一个调用方便的方法,把该参数传入方法即可返回一个相应的按钮对象,此时,就 可以使用简单工厂模式。
3.优缺点:
优点:工厂类包含产品的判断逻辑,可以决定创建哪一个产品类的实例,客户端可以免除直接创建产品对象 的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于 创建对象。
缺点:由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。使用简单工厂模 式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。系统扩展困难,一旦添加新产 品就不得不修改工厂逻辑,在产品类型较多时,可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
4.简单工厂四个角色:
1 工厂角色:负责创建具体的产品。
2 父类产品: 作为所有产品的父类,使用抽象类表示
3 子类产品:具体的产品
4 客户程序:使用工厂和产品的程序 5.案例: 服装厂:生产服装 分析: 需要一个服装工厂类:工厂,类中具有生产服装的功能(创建服装对象) ClothesFactory 服装类(父 类产品):抽象类表示,Clothes 服装子类(具体产品): 普通类表示,裤子(Trousers)、T恤(TShirt)、夹克
(Jacket) 客户程序:使用工厂的程序。
public interface Human {
public void say();
}
然后定义男人和女人,同样都有说话的方法。
package com.roc.factory;
public class Man implements Human {
/* say method
* @see com.roc.factory.Human#say()
*/
@Override
public void say() {
System.out.println("男人");
}
}
package com.roc.factory;
public class Woman implements Human {
@Override
public void say() {
System.out.println("女人");
}
}
最后写一个工厂类,用来创造男人和女人。第一种方式是使用逻辑判断的方式实现的。
package com.roc.factory;
public class SampleFactory {
public static Human makeHuman(String type){
if(type.equals("man")){
Human man = new Man();
return man;
}else if(type.equals("womman")){
Human woman = new Woman();
return woman;
}else{
System.out.println("生产不出来");
return null;
}
}
}
最后是客户端的代码
package com.roc.factory;
public class Client {
Human man = SampleFactory1.makeHuman(Man.class);
man.say();
Human woman = SampleFactory1.makeHuman(Woman.class);
woman.say();
}
}
装饰者模式
装饰模式指的是在不必改变原类文件和继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对 象,也就是装饰来包裹真实的对象。 应用场景:需要扩展一个类的功能,或给一个类添加附加职责
1 抽象类 ReadFile ‐‐>read抽象方法 2 定义一些子类 ReadTextFile 读取文本文件 ReadMusicFile 读取音乐文件 ReadVideoFile 读取视频文件 3 要求:提高三个类的功能 带缓冲
3.1继承 BufferedReadTextFile继承ReadTextFile 重写 read方法
BufferedReadMusicFile继承ReadMusicFile 重写 read BufferedReadVideoFile继承ReadVideoFile 重写 read
缺点:1 类体系太庞大 2 耦合性太高
3.2装饰者设计模式 :采用组合的关系
BufferedReadFile{
private ReadFile readFile;
public BufferedReadFile(ReadFile readFile){
this.readFile=readFile; }
public void read(){ ///
}
}
优点:耦合性低,提高重用性
== 代码实现==:
抽象类
/**
* ckd 2019/8/9 18:55
*/
public abstract class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
public Person(String name) {
super();
this.name = name;
}
public abstract void eat();
}
学生类
/**
* ckd 2019/8/9 18:56
*/
public class Student extends Person{
public Student(String name) {
super (name);
}
public Student() {
super();
}
public void eat(){
System.out.println("学生吃饭了");
}
}
老师类
/**
* ckd 2019/8/9 18:56
*/
public class Teacher extends Person{
public Teacher(String name) {
super( name );
}
public Teacher() {
super();
}
public void eat(){
System.out.println("老师开始吃饭");
}
}
装饰类
/**
* ckd 2019/8/9 18:56
*/
public class Strong {
private Person person;
public Strong(Person person){
super();
this.person=person;
}
public void eat(){
System.out.println(person.getName()+"喝一口");
System.out.println(person.getName()+"睡一会");
person.eat();
}
}
测试类
/**
* ckd 2019/8/9 18:56
*/
public class Test {
public static void main(String[] args){
Student s1=new Student( "chen" );
Teacher t1=new Teacher( "kai" );
/* s1.eat();
t1.eat();*/
Strong s3=new Strong(s1);
s3.eat();
}
}
生产消费者模式
设置一块缓冲区,作为仓库或者容器,生产者可以王里面放入产品,同时,消费者也可以从里面提取走产品,为了解决其中的同步问题,需要一种方法或者机制来保证两者之间的同步,为了保证同步,需要给资源加锁,确定同一时刻同一个资源只能被一个线程访问。
使用方法
wait:当临界资源已满或者临界资源为空时,当前线程可以使用wait方法。放弃锁,进行等待,让其他线程去执行
notify:当生产者或者消费者向缓冲区放入一块产品时,可以使用notify向其他线程发出可以执行的通知,同时放弃锁,使自己处于等待状态
public class Produce {
public Object object;
public ArrayList<Integer> list;//用list存放生产之后的数据,最大容量为1
public Produce(Object object,ArrayList<Integer> list ){
this.object = object;
this.list = list;
}
public void produce() {
synchronized (object) {
/*只有list为空时才会去进行生产操作*/
try {
while(!list.isEmpty()){
System.out.println("生产者"+Thread.currentThread().getName()+" waiting");
object.wait();
}
int value = 9999;
list.add(value);
System.out.println("生产者"+Thread.currentThread().getName()+" Runnable");
object.notifyAll();//然后去唤醒因object调用wait方法处于阻塞状态的线程
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Consumer {
public Object object;
public ArrayList<Integer> list;//用list存放生产之后的数据,最大容量为1
public Consumer(Object object,ArrayList<Integer> list ){
this.object = object;
this.list = list;
}
public void consmer() {
synchronized (object) {
try {
/*只有list不为空时才会去进行消费操作*/
while(list.isEmpty()){
System.out.println("消费者"+Thread.currentThread().getName()+" waiting");
object.wait();
}
list.clear();
System.out.println("消费者"+Thread.currentThread().getName()+" Runnable");
object.notifyAll();//然后去唤醒因object调用wait方法处于阻塞状态的线程
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ProduceThread extends Thread {
private Produce p;
public ProduceThread(Produce p){
this.p = p;
}
@Override
public void run() {
while (true) {
p.produce();
}
}
}
package ProduceConsumer;
public class ConsumeThread extends Thread {
private Consumer c;
public ConsumeThread(Consumer c){
this.c = c;
}
@Override
public void run() {
while (true) {
c.consmer();
}
}
}
package ProduceConsumer;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
Object object = new Object();
ArrayList<Integer> list = new ArrayList<Integer>();
Produce p = new Produce(object, list);
Consumer c = new Consumer(object, list);
ProduceThread[] pt = new ProduceThread[2];
ConsumeThread[] ct = new ConsumeThread[2];
for(int i=0;i<2;i++){
pt[i] = new ProduceThread(p);
pt[i].setName("生产者 "+(i+1));
ct[i] = new ConsumeThread(c);
ct[i].setName("消费者"+(i+1));
pt[i].start();
ct[i].start();
}
}
}