一朵花有Open和Close两种状态,3只蜜蜂在花Open的时候去采蜜,在花Close的时候回巢,用面向对象技术和Design Pattern方法模拟上面过程,输出如下:
Flower Open
Hummingbird 1's breakfast time
Hummingbird 2's breakfast time
Hummingbird 3's breakfast time
Flower Close
Hummingbird 1's bed time
Hummingbird 2's bed time
Hummingbird 3's bed time
要求:
1.使用一种Design Pattern方法,使花和蜂鸟之间松耦合,用Objective-C/Swift写出上面描述过程的完整程序;
2.画出UML类图。
Objective-C 实现:有耦合的
创建花类:
#import <Foundation/Foundation.h>
#import "Bee.h"
NS_ASSUME_NONNULL_BEGIN
@interface Flower : NSObject
/// 1 花开 其他 花谢
@property (nonatomic, assign) NSInteger status;
- (void)addBee:(Bee *)bee;
- (void)addBees:(NSArray <Bee *> *)bees;
- (void)removeBee:(Bee *)bee;
@end
NS_ASSUME_NONNULL_END
#import "Flower.h"
@interface Flower ()
@property (nonatomic, strong) NSMutableArray < Bee *> *beeArray;
@end
@implementation Flower
- (instancetype)init {
self = [super init];
if (self) {
self.beeArray = @[].mutableCopy;
}
return self;
}
- (void)setStatus:(NSInteger)status {
_status = status;
[self notifyObserves:self.beeArray];
}
- (void)addBee:(nonnull Bee *)bee {
[self.beeArray enumerateObjectsUsingBlock:^(Bee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (obj.id.intValue == bee.id.intValue) {
return;
}
}];
[self.beeArray addObject:bee];
}
- (void)addBees:(NSArray<Bee *> *)bees {
[self.beeArray removeAllObjects];
self.beeArray = bees.mutableCopy;
}
- (void)removeBee:(nonnull Bee *)bee {
[self.beeArray enumerateObjectsUsingBlock:^(Bee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (obj.id.intValue != bee.id.intValue) {
return;
}
}];
[self.beeArray removeObject:bee];
}
- (void)notifyObserves:(nonnull NSArray<Bee *> *)observes {
if (self.status == 1) {
NSLog(@"Flower Open");
} else {
NSLog(@"Flower Close");
}
[observes enumerateObjectsUsingBlock:^(Bee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj onValueChanged:self.status];
}];
}
- (void)dealloc {
[self.beeArray removeAllObjects];
self.beeArray = nil;
}
@end
创建蜂鸟类:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Bee : NSObject
@property (nonatomic, strong) NSNumber *id;
@property (nonatomic, strong) NSString *name;
- (instancetype)initWithID:(NSNumber *)number name:(NSString *)name;
- (void)onValueChanged:(NSInteger)status;
@end
NS_ASSUME_NONNULL_END
#import "Bee.h"
@implementation Bee
- (instancetype)initWithID:(NSNumber *)number name:(NSString *)name {
self = [super init];
if (self) {
_id = number;
_name = name;
}
return self;
}
- (void)onValueChanged:(NSInteger)status {
if (status == 1) {
NSString *log = [NSString stringWithFormat:@"%@'s eating time",self.name];
NSLog(@"%@",log);
} else {
NSString *log = [NSString stringWithFormat:@"%@'s bed time",self.name];
NSLog(@"%@",log);
}
}
@end
调用:
#import "ViewController.h"
#import "Flower.h"
@interface ViewController ()
@property (nonatomic, strong) Flower *flower;
@property (weak, nonatomic) IBOutlet UIButton *swiftButton;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.flower = [[Flower alloc] init];
Bee *bee1 = [[Bee alloc] initWithID:@1 name:@"Bee 1"];
Bee *bee2 = [[Bee alloc] initWithID:@2 name:@"Bee 2"];
Bee *bee3 = [[Bee alloc] initWithID:@3 name:@"Bee 3"];
// [self.flower addBee:bee1];
// [self.flower addBee:bee2];
// [self.flower addBee:bee3];
[self.flower addBees:@[bee1,bee2,bee3]];
}
- (IBAction)didTaaped:(UIButton *)sender {
sender.selected = !sender.selected;
self.flower.status = sender.selected;
NSString *status = sender.selected ? @"Open" : @"Close";
[self.swiftButton setTitle:status forState:0];
}
@end
Objective-C 实现:代理改良版,松耦合
#ifndef HummingProtocol_h
#define HummingProtocol_h
typedef NS_ENUM(NSInteger, FlowerStatus) {
FlowerStatusClose = 0,
FlowerStatusOpen = 1,
};
/// 花期变化的协议
@protocol ObserveProtocol <NSObject>
- (void)flowerOnValueChanged:(FlowerStatus)status;
@end
#endif /* HummingProtocol_h */
#import <Foundation/Foundation.h>
#import "HummingProtocol.h"
#import "Bee.h"
NS_ASSUME_NONNULL_BEGIN
@interface Flower : NSObject
/// 1 花开 其他 花谢
@property (nonatomic, assign) FlowerStatus status;
@property (nonatomic, weak) id <ObserveProtocol> delegate;
@end
NS_ASSUME_NONNULL_END
#import "Flower.h"
@interface Flower ()
@end
@implementation Flower
- (void)setStatus:(FlowerStatus)status {
_status = status;
if (status == FlowerStatusOpen) {
NSLog(@"Flower Open");
} else {
NSLog(@"Flower Close");
}
//这里可以使用通知
if (self.delegate && [self.delegate respondsToSelector:@selector(flowerOnValueChanged:)]) {
[self.delegate flowerOnValueChanged:status];
}
}
@end
#import <Foundation/Foundation.h>
#import "HummingProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface Bee : NSObject
@property (nonatomic, strong) NSNumber *id;
@property (nonatomic, strong) NSString *name;
- (instancetype)initWithID:(NSNumber *)number name:(NSString *)name;
/// 蜜蜂采蜜的方法
/// @param status 花期状态
- (void)onValueChanged:(FlowerStatus)status;
@end
NS_ASSUME_NONNULL_END
#import "Bee.h"
@implementation Bee
- (instancetype)initWithID:(NSNumber *)number name:(NSString *)name {
self = [super init];
if (self) {
_id = number;
_name = name;
}
return self;
}
- (void)onValueChanged:(FlowerStatus)status {
if (status == FlowerStatusOpen) {
NSString *log = [NSString stringWithFormat:@"%@'s eating time",self.name];
NSLog(@"%@",log);
} else {
NSString *log = [NSString stringWithFormat:@"%@'s bed time",self.name];
NSLog(@"%@",log);
}
}
@end
代理改良版,耦合度松调用:
#import "ViewController.h"
#import "Flower.h"
@interface ViewController ()<ObserveProtocol>
@property (nonatomic, strong) Flower *flower;
@property (weak, nonatomic) IBOutlet UIButton *swiftButton;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.flower = [[Flower alloc] init];
self.flower.delegate = self;
}
- (IBAction)didTaaped:(UIButton *)sender {
sender.selected = !sender.selected;
self.flower.status = sender.selected;
NSString *status = sender.selected ? @"Open" : @"Close";
[self.swiftButton setTitle:status forState:0];
}
- (void)flowerOnValueChanged:(FlowerStatus)status {
Bee *bee1 = [[Bee alloc] initWithID:@1 name:@"Bee 1"];
Bee *bee2 = [[Bee alloc] initWithID:@2 name:@"Bee 2"];
Bee *bee3 = [[Bee alloc] initWithID:@3 name:@"Bee 3"];
[@[bee1,bee2,bee3] enumerateObjectsUsingBlock:^(Bee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj onValueChanged:status];
}];
}
@end
Swift版本实现:https://segmentfault.com/a/1190000023017604
import Foundation
protocol ObserveProtocol {
var id : Int { get set}
func onValueChanged(_ value : Any?)
}
protocol ObserableProtocol {
var observes : [ObserveProtocol] { get set}
func addObserve(_ observe : ObserveProtocol)
func removeObserve(_ observe : ObserveProtocol)
func notifyObserves(_ observes : [ObserveProtocol])
}
class Obserable<T>: ObserableProtocol {
internal var observes: [ObserveProtocol] = []
func addObserve(_ observe: ObserveProtocol) {
guard self.observes.contains(where: { $0.id == observe.id }) == false else {
return
}
self.observes.append(observe)
}
func removeObserve(_ observe: ObserveProtocol) {
guard let index = self.observes.firstIndex(where: { $0.id == observe.id }) else {
return
}
self.observes.remove(at: index)
}
func notifyObserves(_ observes: [ObserveProtocol]) {
observes.forEach({ $0.onValueChanged(value) })
}
var value: T {
didSet {
self.notifyObserves(self.observes)
}
}
init(value: T) {
self.value = value
}
deinit {
observes.removeAll()
}
}
enum FlowerStatus: String {
case open = "Flower Open"
case close = "Flower Close"
}
class Flower: Obserable<FlowerStatus> {
var status: FlowerStatus {
get {
return self.value
}
set {
print(newValue.rawValue)
self.value = newValue
}
}
}
struct Bee: ObserveProtocol {
var id: Int
var name: String
func onValueChanged(_ value: Any?) {
if let status = value as? FlowerStatus {
if status == .open {
print("\(name)'s breakfast time")
} else {
print("\(name)'s bed time")
}
}
}
}
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
var flower = Flower(value: .close)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let bee1 = Bee.init(id: 1, name: "Bee 1")
let bee2 = Bee.init(id: 2, name: "Bee 2")
let bee3 = Bee.init(id: 3, name: "Bee 3")
self.flower.addObserve(bee1)
self.flower.addObserve(bee2)
self.flower.addObserve(bee3)
}
@IBAction func didButtonTapped(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
let status = sender.isSelected ? "Flower Open" : "Flower Close"
self.button.setTitle(status, for: .normal)
self.flower.status = FlowerStatus(rawValue: status)!
}
}